Рекурсивная ссылка на список внутри себя

Итак, я наткнулся на что-то очень странное в python. Я попытался добавить ссылку на список для себя. Код может помочь продемонстрировать, что я говорю лучше, чем я могу выразить. Я использую редактор IDLE (интерактивный режим).

>>>l=[1,2,3]
>>>l.append(l)
>>>print(l)
[1,2,3,[...]]
>>>del l[:-1]
>>>print(l)
[[...]]

До сих пор выход ожидался. Но когда я это делаю.

y=l[:]
print(y)

Мне кажется, что вывод должен быть

[[...]]

Но это

[[[...]]]

По-видимому, вместо создания копии списка он помещает ссылку на список в y.

y [0] - l возвращает True. Кажется, я не могу найти для этого хорошего объяснения. Любые идеи?

Ответ 1

Разница заключается только в том, как отображается список. То есть значение y - это именно то, что вы ожидаете.

Разница в том, как отображаются списки, возникает из-за того, что в отличие от l, y не является списком саморегуляции:

l[0] is l
=> True
y[0] is y
=> False

y не является саморегуляцией, потому что y не ссылается на y. Он ссылается на l, который является самореференцией.

Следовательно, логика, которая переводит список в строку, обнаруживает потенциальную бесконечную рекурсию на один уровень глубже при работе с y, чем на l.

Ответ 2

Это вполне ожидаемо. Когда Python печатает рекурсивные списки, он проверяет, что список, который он печатает, еще не встречается, и если он имеет отпечатки [...]. Важно понять, что он не тестирует равенство (как в ==), а для identity (как в is). Следовательно,

  • при печати l = [l]. У вас l[0] is l возвращается True, и поэтому он печатает [[...]].

  • теперь y = l[:] делает копию l, и поэтому y is l возвращает False. Итак, вот что происходит. Он начинает печать y, поэтому он печатает [??? ], где ??? заменяется печатью y[0]. Теперь y[0] является l и не является y. Поэтому он печатает [[???]] с заменой ??? на y[0][0]. Теперь y[0][0] есть l, который уже встречается. Поэтому он печатает [...], давая наконец [[[...]]].

Ответ 3

Вам нужно иметь полную копию объектов. Вам нужно использовать copy.deepcopy, и вы увидите ожидаемые результаты.

>>> from copy import deepcopy
>>> l=[1,2,3]
>>> l.append(l)
>>> print(l)
[1, 2, 3, [...]]
>>> del l[:-1]
>>> print(l)
[[...]]
>>> y=deepcopy(l)
>>> print(y)
[[...]]
>>> y[0] is l
False
>>>

Когда вы используете ноту фрагмента для копирования списка, сохраняются внутренние ссылки, которые вызывают поведение, которое вы наблюдаете.

Ответ 4

Slicing генерирует список элементов. Существует только один элемент - список "l". Итак, у нас есть новый список из одного элемента - список "l".