【问题标题】:python: Why listA.append('a') affects listB? [duplicate]python: 为什么 list.append('a') 会影响列表? [复制]
【发布时间】:2013-10-03 17:32:58
【问题描述】:

这是我的代码:

In [8]: b=dict.fromkeys([1,2,3,4], [])

In [9]: b[1].append(1)

In [10]: b[2].append(2)

In [11]: b[1]
Out[11]: [1, 2]

In [12]: b[2]
Out[12]: [1, 2]

In [13]: b
Out[13]: {1: [1, 2], 2: [1, 2], 3: [1, 2], 4: [1, 2]}

而我期望:{1: [1], 2: [2], 3: [], 4: []}

我猜这可能是由于 b[X] 只是一个“引用”,它们都引用同一个列表。

然后我将 [] 替换为 int 对象。结果让我更加困惑:

In [15]: b=dict.fromkeys([1,2,3,4], 1)

In [16]: b[1] += 1

In [17]: b[2] += 1

In [18]: b
Out[18]: {1: 2, 2: 2, 3: 1, 4: 1}

在这种情况下,这个 int 对象 1 不是引用。

然后我将 [] 替换为 ['a']:

In [19]: b=dict.fromkeys([1,2,3,4], ['a'])

In [20]: b[1].append(1)

In [21]: b[2].append(2)

In [22]: b
Out[22]: {1: ['a', 1, 2], 2: ['a', 1, 2], 3: ['a', 1, 2], 4: ['a', 1, 2]}

现在 ['a'] 又是一个引用。

谁能告诉我为什么,以及如何在第一种情况下获得预期结果“{1: [1], 2: [2], 3: [], 4: []}”。

感谢任何有用的建议。

【问题讨论】:

    标签: python list


    【解决方案1】:

    因为 dict 中的所有值实际上都是对同一个列表的引用,dict.fromkeys 使用相同的列表对象并将其分配给每个键。由于list.append 是就地操作,因此所有键都会受到影响。

    >>> b = dict.fromkeys([1,2,3,4], [])
    >>> [id(x) for x in b.values()]
    [158948300, 158948300, 158948300, 158948300]
    

    因此,对于可变值,请使用 dict 理解:

    >>> b = {k:[] for k in xrange(1, 5)}
    >>> [id(x) for x in b.values()]
    [158945580, 158948396, 158948108, 158946764]
    

    或者正如@Bakuriu 建议的那样,collections.defaultdict 也可以正常工作:

    >>> from collections import defaultdict
    >>> dic = defaultdict(list)
    >>> dic[1].append(1)
    >>> dic[2].append(2)
    >>> dic
    defaultdict(<type 'list'>, {1: [1], 2: [2]})
    >>> dic[3]
    []
    

    【讨论】:

    • 或者更好:使用defaultdict,这样就无需完全使用fromkeys
    • 谢谢,现在很有意义。
    【解决方案2】:

    它们确实都是参考。不同之处在于您对引用的处理方式。

    当您使用赋值运算符= 时,您将引用设置为不同的对象。 (+= 工作方式相同)。

    当您使用append 时,您正在修改对象而不影响引用。由于fromkeys返回了对同一个对象的多个引用,因此修改会同时出现在所有对象中。

    【讨论】:

    • 这个概念性解释实际上确实解决了 OP 的问题,+1
    • 谢谢,这个回答也增加了我的理解。
    猜你喜欢
    • 2021-08-25
    • 1970-01-01
    • 1970-01-01
    • 2020-05-02
    • 2019-12-25
    • 1970-01-01
    • 1970-01-01
    • 2016-03-11
    • 1970-01-01
    相关资源
    最近更新 更多