Python Forum

Full Version: output list reducing each time through loop
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
In getting empty lists as output, and that is something I don't get.

Expected:
[1,2,3,4,5]
[2,3,4,5]
[3,4,5]
[4,5]
[5]

a = [1,2,3,4,5]
output = []

while a:
  output.append(a)
  a.pop(0)

print(output)
I want a seperate 'output'container so I can use that afterwards.
You are getting list of empty lists, not empty list
Output:
[[], [], [], [], []] >>>
Check this link https://nedbatchelder.com/text/names.html
lists are mutable. when you append a to output on line 5, every list you append refers to same elements. when you pop element on line 6 you pop it out from all the lists. To fix this, you need to append copy of a to output
a = [1,2,3,4,5]
output = []
 
while a:
  output.append(a[:])
  a.pop(0)
 
print(output)
Output:
[[1, 2, 3, 4, 5], [2, 3, 4, 5], [3, 4, 5], [4, 5], [5]] >>>
Thanks Buran,

I think it makes sense to me, but I'll read the link you posted so I can fully understand it! Food for thought!

3Pinter
Hey Buran,

Super interesting article and it explained a lot to me. However I don't get a tiny thing: lists are mutable, okay. And therefor doing this:

start = [1,2,3,4,5]
new = []
t = True
for s in start:
    new.append(start)
    if t:
    	start.pop(0)
        t = False
print(new)
"new" will output [2,3,4,5] a few times. As expected.

But since lists are mutable I would expect that changing "start" to a new definition would alter the "new" list as well.

start = [1,2,3,4,5]
new = []
t = True
for s in start:
    new.append(start)
    if t:
    	start.pop(0)
        t = False
start = ["test"]
print(new)
But python will still output [2,3,4,5] a few times.

Why doesn't it output "test" a few times?
on line 9 you don't mutate start, you create new list, i.e. start now points to different list:

start = [1,2,3,4,5]
print(f'id of start: {id(start)}')
new = []
print(f'id of new: {id(new)}')
t = True
for s in start:
    new.append(start)
    if t:
        start.pop(0)
        t = False
start = ['test']
print(f'id of start: {id(start)}')
print(new)
print(f'id of new: {id(new)}')
Output:
id of start: 4088456 id of new: 32132424 id of start: 32124040 [[2, 3, 4, 5], [2, 3, 4, 5], [2, 3, 4, 5], [2, 3, 4, 5]] id of new: 32132424 >>>
as you can see the id of start changes, while the id of new is the same


Now, here is what you were looking/expecting:

start = [1,2,3,4,5]
print(f'id of start: {id(start)}')
new = []
print(f'id of new: {id(new)}')
t = True
for s in start:
    new.append(start)
    if t:
        start.pop(0)
        t = False
print(new)
start[0] = 'test'
print(f'id of start: {id(start)}')
print(new)
print(f'id of new: {id(new)}')
Output:
id of start: 4153992 id of new: 31997384 [[2, 3, 4, 5], [2, 3, 4, 5], [2, 3, 4, 5], [2, 3, 4, 5]] id of start: 4153992 [['test', 3, 4, 5], ['test', 3, 4, 5], ['test', 3, 4, 5], ['test', 3, 4, 5]] id of new: 31997384 >>>
here you mutate the original start (id is not changed) and you can see that change is also reflected in new
ah, python too has id's. that explains it all.

Thanks again Buran for your explanation!
Additional tidbit: if you really after "output 'test' few times" then it can be done this way:

start[:] = ['test']