So I came across something very weird in python. I tried adding a reference to the list to itself. The code might help demonstrate what I am saying better than I can express. I am using IDLE editor(interactive mode).
>>>l=[1,2,3]
>>>l.append(l)
>>>print(l)
[1,2,3,[...]]
>>>del l[:-1]
>>>print(l)
[[...]]
So far the output is as expected. But when I do this.
y=l[:]
print(y)
To me it seems that the output should be
[[...]]
But it is
[[[...]]]
Apparently instead of creating a copy of the list, it puts a reference to the list in y.
y[0] is l returns True. I can't seem to find a good explanation for this. Any ideas?
The difference is only in the way the list is displayed. I.e. the value of y
is exactly what you'd expect.
The difference in the way the lists are displayed results from the fact that, unlike l
, y
is not a self-referencing list:
l[0] is l
=> True
y[0] is y
=> False
y
is not self-referencing, because y
does not reference y
. It references l
, which is self-referencing.
Therefor, the logic which translates the list to a string detects the potential infinite-recursion one level deeper when working on y
, than on l
.
This is perfectly expected. When Python prints recursive lists, it checks that the list it is printing hasn't yet been encountered and if it has prints [...]
. An important point to understand is that it doesn't test for equality (as in ==
) but for identity (as in is
). Therefore,
when you print
l = [l]
. You havel[0] is l
returnsTrue
and therefore it prints[[...]]
.now
y = l[:]
makes a copy ofl
and thereforey is l
returnsFalse
. So here is what happens. It starts printingy
so it prints [ ??? ] where???
is replaced by the printing ofy[0]
. Nowy[0]
isl
and is noty
. So it prints[[???]]
with???
replaced byy[0][0]
. Nowy[0][0]
isl
which has already been encountered. So it prints[...]
for it giving finally[[[...]]]
.
You need to have a full copy of the objects. You need to use copy.deepcopy
and you would see the expected results.
>>> 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
>>>
When you use the slice notation to copy the list, the inner references are retained which cause the behavior that you observe.
Slicing generates list of items. There is only one item - list "l". So, we have new list of one element - list "l".
来源:https://stackoverflow.com/questions/21798483/recursive-reference-to-a-list-within-itself