3

I am currently iterating through one value of a list. On each iteration, I append the list to a new list, in order to have a list of lists. However, the outputs that I am receiving aren't what I am expecting them to be.

I've simplified the problem as much as possible and have arrived at this :

def Function():
     ListOfLists = []
     Lists = [0]
     for j in range(0, 5):
         Lists[0] = Lists[0] + 1
         print(Lists)
         ListOfLists.append(Lists)
     print("ListofLists:")
     print(ListOfLists)

Function()

The output gives me this :

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

I would've expected the output to be :

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

Where am I going wrong? Thanks

Hunted
  • 88
  • 1
  • 7

4 Answers4

3

You have to append a copy of list. When you say List, it's a reference. When List changes, ListOfLists changes. Making a copy prevents this so-called (un)expected behaviour.

Replace this line of code:

ListOfLists.append(Lists)

with:

ListOfLists.append(Lists[:])
Austin
  • 25,759
  • 4
  • 25
  • 48
  • For my own understanding, this means that ListOfLists.append(Lists) is storing a reference to Lists? Edit : hygull answered this comment just below. Thanks! – Hunted Oct 27 '19 at 04:27
0

That is because all appended instances are referring to the same address in memory.

PROBLEM:

In [1]: def Function(): 
   ...:      ListOfLists = [] 
   ...:      Lists = [0] 
   ...:      for j in range(0, 5): 
   ...:          Lists[0] = Lists[0] + 1 
   ...:          print(Lists) 
   ...:          ListOfLists.append(Lists) 
   ...:      print("ListofLists:") 
   ...:      print(ListOfLists) 
   ...:  
   ...: Function()                                                                             
[1]
[2]
[3]
[4]
[5]
ListofLists:
[[5], [5], [5], [5], [5]]

SOLUTION:

Check Check What is the difference between list and list[:] in python?.

Use [:] for creating a different object (shallow copy) in this case. You read about deep copy and shallow copy in Python to understand more about how actually Python treats with references. For more details, check https://www.programiz.com/python-programming/shallow-deep-copy.

Replace ListOfLists.append(Lists) with ListOfLists.append(Lists[:]).

In [2]: def Function(): 
   ...:      ListOfLists = [] 
   ...:      Lists = [0] 
   ...:      for j in range(0, 5): 
   ...:          Lists[0] = Lists[0] + 1 
   ...:          print(Lists) 
   ...:          ListOfLists.append(Lists[:]) 
   ...:      print("ListofLists:") 
   ...:      print(ListOfLists) 
   ...:  
   ...: Function()                                                                             
[1]
[2]
[3]
[4]
[5]
ListofLists:
[[1], [2], [3], [4], [5]]

In [3]:            
hygull
  • 8,464
  • 2
  • 43
  • 52
0

Try this:

def Function():
    ListOfLists = []
    for j in range(0, 5):
        ListOfLists.append([j+1])
    print(ListOfLists)
Function() 
JJSSEE
  • 29
  • 6
  • While the output of this code does match the output that I was expecting, it doesn't work in the larger problem / code that I was trying to code. Thanks though! – Hunted Oct 27 '19 at 04:45
0

When you append Lists to ListofLists, it does not make a separate copy the list and append it. Instead, it just appends a reference to the List list inside ListofLists. This is often confusing as a beginner. If you mutate List next time, the value inside ListofLists will also change as both of them are referencing the same list. If you want to have a completely separate list every time, you should use copy() method on list or `Lists[:]'. Or you can create the list on the fly while appending, as follows:

ListofLists = []
for number in range(1,6):
    print([number])
    ListofLists.append([number])
print(ListofLists)

And much more simple and readable way would be to use a list comprehension, like follows:

ListofLists = [[number] for number in range(1, 6)]
print(ListofLists)
Hanif Ali
  • 1
  • 3