Рекурсивная ссылка на список внутри себя
Итак, я наткнулся на что-то очень странное в 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".