递归引用自身内的列表

时间:2014-02-15 13:57:11

标签: python list self-reference repr

所以我在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。我似乎无法找到一个很好的解释。有什么想法吗?

4 个答案:

答案 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”。