所以我在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。我似乎无法找到一个很好的解释。有什么想法吗?
答案 0 :(得分:8)
区别仅在于列表的显示方式。即y
的值正是您所期望的。
列表显示方式的不同之处在于,与l
不同,y
不是自引用列表:
l[0] is l
=> True
y[0] is y
=> False
y
不是自我引用,因为y
未引用y
。它引用l
,它是自引用的。
因此,将列表转换为字符串的逻辑在处理y
时比在l
上检测到更深层次的潜在无限递归。
答案 1 :(得分:3)
这是完全可以预期的。当Python打印递归列表时,它会检查是否尚未遇到它正在打印的列表,以及它是否打印了[...]
。需要了解的一点是,它不会测试相等(如==
),而是身份(如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
。所以它会打印[...]
,最后给出[[[...]]]
。
答案 2 :(得分:2)
您需要拥有对象的完整副本。您需要使用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
>>>
使用切片表示法复制列表时,会保留内部引用,这会导致您观察到的行为。
答案 3 :(得分:1)
切片生成项目列表。只有一个项目 - 列表“l”。所以,我们有一个新元素列表 - 列出“l”。