why can’t I change only a single element in a nested list in Python

I just met something really strange of Python:

>>> out=[[0]*3]*3
>>> out
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> out[0][1]
0
>>> out[0][1]=9
>>> out
[[0, 9, 0], [0, 9, 0], [0, 9, 0]]

well, obviously, what I want is :

[[0, 9, 0], [0, 0, 0], [0, 0, 0]]

isn’t strange? I’m not very familiar with Python, but Python always impresses me with its intuitive behavior. But how it comes up with this?
… and how can I get what I need?

thanks!

Watt

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

A strange behaviour indeed, but that’s only because * operator makes shallow copies, in your case – shallow copies of [0, 0, 0] list. You can use the id() function to make sure that these internal lists are actually the same:

out=[[0]*3]*3
id(out[0])
>>> 140503648365240
id(out[1])
>>> 140503648365240
id(out[2])
>>> 140503648365240

Comprehensions can be used to create different lists as follows:

out = [ [0]*3 for _ in range(3) ]

Method 2

Using * to duplicate elements in lists is a shallow copy operation, so you will end up with multiple references to the same mutable objects if you use this on a list that contains mutable objects.

Instead, use the following to initialize your nested list:

out = [[0]*3 for _ in range(3)]

You can see that with your method, each entry in out is actually a reference to the same list, which is why you see the behavior that you do:

>>> out = [[0]*3]*3
>>> out[0] is out[1] is out[2]
True


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x