3

for example, why can't f print out with numbers 1-10 in a list.

f = []
a = []
for i in range(10):
  a.append(i)
  f.append(a)
  a.clear()
print(f)

I understand there are other ways to do this exact program but I'm curious as to why python outputs f as a list with a bunch of empty lists: [[][][][][][][][][][]].

Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • 2
    It works as expected. You add something to a, add a to f and you clear a. This makes f contains empty lists. – balderman Nov 27 '20 at 13:42
  • Does this answer your question? [List of lists changes reflected across sublists unexpectedly](https://stackoverflow.com/questions/240178/list-of-lists-changes-reflected-across-sublists-unexpectedly) – superb rain Nov 27 '20 at 13:47
  • Am I mistaken, or did five people all with thousands of reputation not recognize this as yet another duplicate of the second-most duplicated Python question? – superb rain Nov 27 '20 at 14:10
  • @superbrain people have a lot of time and energy to guide other people on their problem :D and they love to do it – sahasrara62 Nov 27 '20 at 14:34

5 Answers5

3

You add the same a to f multiple times, and clear it on each iteration. Since it's the same list, when you clear it, you'll see this clearing in all of f's elements. The correct way of writing this snippet is to use a new list in every iteration:

for i in range(10):
  a = []
  a.append(i)
  f.append(a)

Of course, this could be shortened considerably using a list comprehension:

f = [[i] for i in range(10)]
Mureinik
  • 297,002
  • 52
  • 306
  • 350
1

When you do f.append(a) you append a reference to the array a, it is the same array you add every time. So when you a.clear() you delete the content of f.

To fix your code, you can try this a.copy()

f = []
a = []
for i in range(10):
    a.append(i)
    f.append(a.copy())
    a.clear()
print(f)

But better is to use a listcomprehension like this:

f = [[i] for i in range(10)]
Christian Sloper
  • 7,440
  • 3
  • 15
  • 28
1

so when you use the a.clear() ie removing all element from the list then, list object become empty and where ever this object is used all of it's value become empty. this is why you are getting empty list of list in the final output.

what you need to go was, either use deepcopy() or redefined the list object with reference to variable a.

below code is what you are looking for for your solution

f = []
a = []
for i in range(10):
  a.append(i) # use a.extend(i) if you want output [0,1,2,3,4,5,6,7,8,9]
  f.append(a)
  a = []
print(f)
# output [[0], [1], [2], [3], [4], [5], [6], [7], [8], [9]]

Below code is a little behind the scene case why your data which is removed from list a is getting removed from f list itself.

a = []
c = []
print('a->',id(a),'c->', id(c), )
# a-> 139917172826512 c-> 139917172828432
a.append(4)
print("after appending 4 to a , id(a)" ,id(a))
#after appending 4 to a , id(a) 139917172826512
c.append(a)
print("after appending a to c, id (C)-> ", id(c))
#after appending a to c, id (C)->  139917172828432
print("id(c[0]) -> ", id(c[0]), "same as id of aa")
# id(c[0]) ->  139917172826512 same as id of aa
a.clear()
print("clear a = {}, c= {}, id(A) -> {}, id(c) -> {}, id(c[0]) -> {}".format(a,c,id(a), id(c), id(c[0])))
# clear a = [], c= [[]], id(A) -> 139917172826512, id(c) -> 139917172828432, id(c[0]) -> 139917172826512
a.append(4)
print("adding 4 again  a = {}, c= {}, id(A) -> {}, id(c) -> {}, id(c[0]) -> {}".format(a,c,id(a), id(c), id(c[0])))
#adding 4 again  a = [4], c= [[4]], id(A) -> 139917172826512, id(c) -> 139917172828432, id(c[0]) -> 139917172826512
a.pop()
print("removing last element from a  again  a = {}, c= {}, id(A) -> {}, id(c) -> {}, id(c[0]) -> {}".format(a,c,id(a), id(c), id(c[0])))
# removing last element from a  again  a = [], c= [[]], id(A) -> 139917172826512, id(c) -> 139917172828432, id(c[0]) -> 139917172826512
a.append(4)
print("adding 4 again  a = {}, c= {}, id(A) -> {}, id(c) -> {}, id(c[0]) -> {}".format(a,c,id(a), id(c), id(c[0])))
# adding 4 again  a = [4], c= [[4]], id(A) -> 139917172826512, id(c) -> 139917172828432, id(c[0]) -> 139917172826512

a = []
a.append(4)
print("changing the list object of a and intilising it again   a = {}, c= {}, id(A) -> {}, id(c) -> {}, id(c[0]) -> {}".format(a,c,id(a), id(c), id(c[0])))
# changing the list object of a and intilising it again   a = [4], c= [[4]], id(A) -> 139917172767552, id(c) -> 139917172828432, id(c[0]) -> 139917172826512

print("see how id associated with the c[0] changes")
# see how id associated with the c[0] changes
sahasrara62
  • 10,069
  • 3
  • 29
  • 44
0

You must append a copy of a to f, because when appending with a, it will be cleared too inside f. Try this instead:

f = []
a = []
for i in range(10):
    a.append(i)
    f.append(list(a)) #amended line
    a.clear()

>>>print(f)

[[0], [1], [2], [3], [4], [5], [6], [7], [8], [9]]
IoaTzimas
  • 10,538
  • 2
  • 13
  • 30
0

The concept you're missing is copy by value versus copy by reference. When working with objects in python (in this case the list named a) you're working with references (aka pointers). When you append a to f then clear a you're referencing (pointing to) the exact same object in memory. That's why a clear of a will affect the contents of f.

To instead copy the value of a, you'll need to create a new list:

f = []
a = []
for i in range(10):
  a.append(i)
  f.append([*a])
  a.clear()
print(f)

In this case, f is getting a new instance of a list that's initialized with the same contents as a. This will result in:

[[0], [1], [2], [3], [4], [5], [6], [7], [8], [9]]

smassey
  • 5,875
  • 24
  • 37