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

4

4 回答 4

8

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

列表显示方式的不同是因为与 不同ly它不是自引用列表:

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

y不是自引用,因为y不引用y. 它引用l,这是自引用的。

y因此,将列表转换为字符串的逻辑在处理时检测到潜在的无限递归比在上更深一层l

于 2014-02-15T14:08:50.523 回答
3

这是完全可以预料的。当 Python 打印递归列表时,它会检查它正在打印的列表是否尚未遇到,以及它是否有 prints [...]。要理解的重要一点是,它不测试相等性(如==),而是测试身份(如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已经遇到的。所以它会打印[...]给它 finally [[[...]]]

于 2014-02-15T14:09:12.607 回答
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
>>>

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

于 2014-02-15T14:20:51.673 回答
1

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

于 2014-02-15T14:10:41.923 回答