0

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?

5
Contributors
5
Replies
22
Views
10 Years
Discussion Span
Last Post by Mathhax0r
0

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

0

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!

0

The id() test sheds some more light on this ...

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
0

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.

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)]
This question has already been answered. Start a new discussion instead.
Be sure to adhere to our posting rules.