开发者

Python list confusion [duplicate]

This question already has answers here: List of lists changes reflected across sublists unexpectedly (17 answers) Closed 1 year ago.

Let's say I have the following code:

a_list = [[0]*10]*10

This generates the following list:

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

Then I want to modify the first element in the first list:

a_list[0][0] = 23

I expected only the first element of the list to be modified, but actually the first element of each list was changed:

[[23, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [23, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [23, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [23, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [23, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [23, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [23, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [23, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [23, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [23, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

I managed to find another way to represent my data to avoid this but why is this happening? Why isn't just the first list chang开发者_如何学Ced? When I do the second *10, does Python actually copy the first list's address instead of allocating a new memory block?


Your hunch about copying addresses is correct. Think about it like this:

sub_list = [0] * 10
a_list = [sub_list] * 10

This code is actually equivalent to the code you have posted above. What this means is that you are actually changing the same list sub_list whenever you change any element of a_list. You can even make sure of it by typing:

a_list = [[0] * 10] * 10
for n in a_list:
    print id(n)

And it will show up the same for every element. To remedy this, you should use:

a_list = [[0] * 10 for _ in range(10)]

In order to create a new sublist for every element of a_list.


Lists contain references to objects. Multiplication on lists simply repeats the references (to the same objects!). While this is fine for immutable objects (like integers), what you are getting is multiple references to the same list.

Create separate lists with this pattern [[0]*10 for _ in xrange(10)].


Why isn't just the first list changed?

The reason is simple, there really is only 1 list, not 10 - just as you already suspected:

In [1]: [[0]*10]*10
Out[1]:
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

In [2]: map(id, _)
Out[2]:
[54094624,
 54094624,
 54094624,
 54094624,
 54094624,
 54094624,
 54094624,
 54094624,
 54094624,
 54094624]

If you want to create 10 lists, you can achieve this easily via an expression like

[[0]*10 for x in xrange(10)]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜