Умножение списка Python: [[...]] * 3 делает 3 списка, которые зеркально отражают друг друга при изменении

Почему это происходит? Я действительно не понимаю:

>>> P = [ [()]*3 ]*3
>>> P
[[(), (), ()], [(), (), ()], [(), (), ()]]
>>> P[0][0]=1
>>> P
[[1, (), ()], [1, (), ()], [1, (), ()]]

Ответ 1

Вы сделали 3 ссылки на один и тот же список.

>>> a = b = []
>>> a.append(42)
>>> b
[42]

Вы хотите сделать это:

P = [[()] * 3 for x in range(3)]

Ответ 2

Списки изменяются, и умножение списка на число не копирует его элементы. Вы можете попробовать изменить его на понимание списка, поэтому он будет оценивать [()]*3 три раза, создавая три разных списка:

P = [ [()]*3 for i in range(3) ]

Ответ 3

Это фактически тот же самый внутренний список (та же ссылка), который дублируется 3 раза, поэтому, когда вы меняете какой-либо из них, вы на самом деле изменяете их все.

Итак, внутренний список [()]*3 создает список из трех кортежей. Но тогда этот список дублируется три раза. Однако в python это действительно список ссылок, которые умножаются, поэтому ссылка дублируется, но каждая ссылка все еще указывает на один и тот же базовый список.

Ответ 4

Вы также можете записать его так, что имеет преимущество при отображении структуры [[()]*3]*3

>>> P=[i[:] for i in [[()]*3]*3]
>>> P[0][0]=1
>>> P
[[1, (), ()], [(), (), ()], [(), (), ()]

Он также немного быстрее, чем использование диапазона. Из оболочки ipython:

In [1]: timeit P = [ [()]*3 for i in range(3) ]
1000000 loops, best of 3: 1.41 us per loop

In [2]: timeit P=[i[:] for i in [[()]*3]*3]
1000000 loops, best of 3: 1.27 us per loop