【问题标题】:Why does foo.append(bar) affect all elements in a list of lists?为什么 foo.append(bar) 会影响列表列表中的所有元素?
【发布时间】:2011-09-15 15:51:06
【问题描述】:

我创建了一个列表列表并希望将项目附加到各个列表中,但是当我尝试附加到其中一个列表 (a[0].append(2)) 时,该项目会添加到所有列表中。

a = []
b = [1]

a.append(b)
a.append(b)

a[0].append(2)
a[1].append(3)
print(a)

给:[[1, 2, 3], [1, 2, 3]]

而我期望:[[1, 2], [1, 3]]

改变我构造初始列表的方式,使 b 成为浮点数而不是列表并将括号放在 .append() 内,给了我想要的输出:

a = []
b = 1

a.append([b])
a.append([b])

a[0].append(2)
a[1].append(3)
print(a)

给:[[1, 2], [1, 3]]

但是为什么呢?结果应该不同是不直观的。我知道这与 multiple references to the same list 的存在有关,但我不知道发生在哪里。

【问题讨论】:

    标签: python list append


    【解决方案1】:

    这是因为列表包含对对象的引用。您的列表不包含[[1 2 3] [1 2 3]],而是[<reference to b> <reference to b>]

    当您更改对象时(通过向b 附加一些内容),您更改的是对象本身,而不是包含该对象的列表。

    要获得您想要的效果,您的列表a 必须包含b 的副本,而不是对b 的引用。要复制列表,您可以使用范围[:]。例如:

    >>> a=[]
    >>> b=[1]
    >>> a.append(b[:])
    >>> a.append(b[:])
    >>> a[0].append(2)
    >>> a[1].append(3)
    >>> print a
    [[1, 2], [1, 3]]
    

    【讨论】:

    • 谢谢,现在很有意义。
    【解决方案2】:

    关键是这部分:

    a.append(b)
    a.append(b)
    

    您将同一个列表追加两次,因此a[0]a[1] 都是对同一个列表的引用。

    在第二个示例中,每次调用 append 时都会创建新列表,例如 a.append([b]),因此它们是使用相同浮点值初始化的单独对象。

    【讨论】:

    • 谢谢,这个回答也增加了我的理解。
    【解决方案3】:

    为了做一个列表的浅拷贝,成语是

    a.append(b[:])
    

    当它加倍时,会导致 a 有两个新的列表 b 副本,这不会给您报告的别名错误。

    【讨论】:

      猜你喜欢
      • 2019-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-01
      • 1970-01-01
      相关资源
      最近更新 更多