954,549 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Making a List of Lists

I was trying to create a 3x3 list of lists, and came up with this surprising behaviour:

# creating a 2D list with an overloaded * operator
mlist3 = [[0]*3]*3
print mlist3  # [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
mlist3[0][0] = 1
print mlist3  # [[1, 0, 0], [1, 0, 0], [1, 0, 0]]  oops!
# populate it properly, now it works!
mlist3[0] = [7, 12, 23]
mlist3[1] = [22, 31, 9]
mlist3[2] = [4, 17, 31]
print mlist3  # [[7, 12, 23], [22, 31, 9], [4, 17, 31]]
mlist3[0][0] = 1
print mlist3  # [[1, 12, 23], [22, 31, 9], [4, 17, 31]]


Any explanation?

sneekula
Nearly a Posting Maven
2,427 posts since Oct 2006
Reputation Points: 961
Solved Threads: 212
 

Yeah, I posted about this, too. Here's the deal:

Because lists are mutable, multiple references to the same list can lead to side effects.

This line:

mlist = [[0]*3]*3


creates a list with three references to the single list [0,0,0].

So when you change that list, all of the references get "automagically" updated.

I haven't decided yet whether this is a "feature" of Python or a "bug." :p

Initializing the array "manually" works, though:

for i in range(3):
    a.append([0,0,0])
>>> a
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> a[0][0] = 1
>>> a
[[1, 0, 0], [0, 0, 0], [0, 0, 0]]
>>>


Jeff

jrcagle
Practically a Master Poster
608 posts since Jul 2006
Reputation Points: 92
Solved Threads: 156
 

Thanks Jeff, so multiplying the sublist [0, 0, 0] by three makes three of exactly the same sublist having the same reference. Appending the list properly won't do that! Wanted to be tricky and paid the price!

sneekula
Nearly a Posting Maven
2,427 posts since Oct 2006
Reputation Points: 961
Solved Threads: 212
 

The id() test sheds some more light on this ...
[php]mlist3 = [[0]*3]*3
print mlist3 # [[0, 0, 0], [0, 0, 0], [0, 0, 0]]

# give it the id() test ...
# all three sublists objects show the same address, 10317016 on my machine
# so they are alias copies, not true copies
print mlist3[0], id(mlist3[0]) # [0, 0, 0] 10317016
print mlist3[1], id(mlist3[1]) # [0, 0, 0] 10317016
print mlist3[2], id(mlist3[2]) # [0, 0, 0] 10317016

mlist4 = []
for k in range(3):
mlist4.append([0, 0, 0])

print mlist4 # [[0, 0, 0], [0, 0, 0], [0, 0, 0]]

# the id() test shows them to be different objects
print mlist4[0], id(mlist4[0]) # [0, 0, 0] 10316936
print mlist4[1], id(mlist4[1]) # [0, 0, 0] 10316976
print mlist4[2], id(mlist4[2]) # [0, 0, 0] 10317096
[/php]

vegaseat
DaniWeb's Hypocrite
Moderator
5,989 posts since Oct 2004
Reputation Points: 1,345
Solved Threads: 1,417
 

I have this same problem, but with a matrix that's 50x1448. i have to manually enter a list with 1448 zeros? that's a nasty surprise.

mike_bow
Newbie Poster
1 post since Nov 2009
Reputation Points: 10
Solved Threads: 0
 

If by manually you mean with 2 for loops or a list comprehension.

listX = [[0 for i in range(1448)] for j in range(50)]
Mathhax0r
Junior Poster in Training
64 posts since Aug 2009
Reputation Points: 12
Solved Threads: 15
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You