Расширение списка списков в Python? [дубликат]

Этот вопрос уже имеет ответ здесь:

Я мог бы отсутствовать, что-то о намеченном поведении списка расширяется, но почему следующее происходит?

x = [[],[]]
y = [[]] * 2

print x       # [[],[]]
print y       # [[],[]]
print x == y  # True

x[0].extend([1])
y[0].extend([1])

print x    # [[1],[]], which is what I'd expect
print y    # [[1],[1]], wtf?

Я предположил бы что * оператор делает что-то неожиданное здесь, хотя я не абсолютно уверен что. Кажется, что что-то продолжается под капотом, это делает исходных X и Y (до вызова, расширяются) не на самом деле быть равным даже при том, что == оператор и repr оба заставили бы его казаться, как будто они были идентичны.

Я только столкнулся с этим, потому что я хотел предварительно заполнить список пустых списков размера, определенного во времени выполнения, и затем понял, что оно не прокладывало себе путь, я вообразил. Я могу найти лучший способ сделать то же самое, но теперь мне любопытно относительно того, почему это не работало. Это - Python 2.5.2 BTW - мне не установили более новую версию поэтому, если это - ошибка, я не уверен, фиксируется ли это уже.

10
задан Paul D. 16 February 2010 в 21:18
поделиться

3 ответа

y содержит две ссылки на один, изменяемый, список.

-121--3090641-

В случае [что-то] * 2 питон просто делает ссылочную копию. Поэтому, если вложенные типы могут изменяться, их изменение будет отражаться в любом месте ссылки на предмет.

В данном примере y [0] и y [1] точки к одному и тому же вложенному объекту списка. Это можно проверить, выполнив команду y [0] y [1] или поочередно id (y [0]) = = id (y [1]) .

Вы можете, однако, переназначить элементы списка, так что если бы вы сделали:

y[0] = [1]

Вы бы повторно привязали первый элемент к новому списку, содержащему элемент «1», и вы бы получили ожидаемый результат.

Контейнеры в python store references, и в большинстве контейнеров последовательности можно ссылаться на один и тот же предмет несколько раз. Список может фактически ссылаться на себя как на элемент, хотя полезность этого ограничена.

Эта проблема не возникла бы, если бы вы умножили список, содержащий неизменяемые типы:

a = [0, 1] * 2

Выше бы дать вам список [0, 1, 0, 1] и действительно оба экземпляра 1 точек к одному и тому же объекту, но поскольку они являются неизменяемыми, вы не можете изменить значение объекта int , содержащего «1,» только переназначить

Таким образом, a [1] = 5 приведет к тому, что a будет отображаться как [0, 5, 0, 1] .

17
ответ дан 3 December 2019 в 17:58
поделиться

Утверждение y = [[]] * 2 связывает y со списком, содержащим 2 копии одного и того же списка. Use:

y = [[], []]

or

y = [[] for n in range(2)]
4
ответ дан 3 December 2019 в 17:58
поделиться

y содержит две ссылки на один изменяемый список.

1
ответ дан 3 December 2019 в 17:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: