2014-02-15 24 views
11

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

回答

8

区别仅在于列表显示的方式。即y的价值正是你所期望的。

在列表中显示的事实结果是,与ly不是自引用列表方式的不同:

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

y不是自我参照,因为y没有引用y。它引用了l,它是自引用的。

因此,将列表翻译为字符串的逻辑在y上比在l上工作时检测到潜在的无限递归更深一级。

3

这是完美的预期。当Python打印递归列表时,它会检查它正在打印的列表是否尚未遇到,并且是否已打印[...]。重要的一点是,它不会测试等于(如==),但身份(如is)。因此,

  • 当您打印l = [l]。您有l[0] is l返回True,因此它打印[[...]]

  • now y = l[:]制作l的副本,因此y is l返回False。所以这里发生了什么。它开始打印y因此它打印[??? ]其中???y[0]的打印替换。现在y[0]l而不是y。所以它打印[[???]]???取代y[0][0]。现在已经遇到y[0][0]l。所以它最终打印[...]给予[[[...]]]

+0

你能否详细说明一下?你失去了我在**“它开始打印y:[???] ..... ** – Guy

+0

另外如果我真的想要一份清单的副本?我知道我可以在这种情况下对y做同样的处理,但为了讨论的缘故,我有办法做到这一点吗? – Guy

+0

@Sabyasachi:这样更清楚吗? – hivert

1

切片生成项目列表。只有一个项目列表“l”。所以,我们有一个元素的新列表 - 列表“l”。

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 
>>> 

当您使用切片表示法复制的清单,内引用保留这会导致你观察到的行为。