代码之家  ›  专栏  ›  技术社区  ›  Guy

对自身内列表的递归引用[重复]

  •  11
  • Guy  · 技术社区  · 10 年前

    所以我在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 回复  |  直到 10 年前
        1
  •  8
  •   shx2    10 年前

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

    不同于 l , y 不是自引用列表:

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

    y 不是自引用,因为 y 不引用 y 。它引用了 l级 ,这是自引用。

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

        2
  •  3
  •   hivert    10 年前

    这是完全意料之中的。当Python打印递归列表时,它会检查是否尚未遇到正在打印的列表,以及是否有打印 [...] 。需要理解的一点是,它不测试 平等 (如 == )但对于 身份 (如 is ). 因此

    • 打印时 l = [l] 。你有 l[0] is l 回报 True 因此它会打印 [[...]] .

    • 现在 y = l[:] 复制 l 因此 y is l 回报 False 。这就是发生的事情。它开始打印 y 所以它在哪里打印 ??? 替换为打印 y[0] 现在 年[0] l级 而不是 y 。所以它会打印 [[???]] 具有 ??? 替换为 y[0][0] 现在 y[0][0]年 l级 这是已经遇到的。所以它会打印 [...] 为它付出最后 [[[...]]] .

        3
  •  2
  •   devnull    10 年前

    你需要一个 完整副本 对象的。你需要使用 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
    >>>
    

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

        4
  •  1
  •   Yuriy Kovalev    10 年前

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