【问题标题】:Do dict keys using list() to copy the same list produce a reference to one another? [duplicate]使用 list() 复制同一列表的 dict 键是否会产生对彼此的引用? [复制]
【发布时间】:2014-01-14 05:29:21
【问题描述】:

我似乎遇到了一个问题,我使用list() 将一个模板列表复制到dict 中的多个键,以便我可以专门更改使用dict 键访问的给定列表的值。但是,我似乎正在对复制列表的键值进行操作。

list1 = [['x', 'y', 0],
        ['m', 'n', 0],
]

dict2 = {'first': list(list1),
        'second': list(list1),
}

def attempt(arg):
    dict_key = dict2[arg]
    for each in dict_key:
        each[2] += 1

attempt('first')
print dict2['first']
print dict2['second']

输出:

[['x', 'y', 1], ['m', 'n', 1]] # expect elems to contain 1 
[['x', 'y', 1], ['m', 'n', 1]] # expect elems to contain 2

看起来 list() 实际上并没有创建一个实际的副本,而是表现得更像一个作业,但这对我来说没有意义。谁能解释一下?

【问题讨论】:

  • @AshwiniChaudhary:从问题中完全看不出他们在问同样的事情……但从答案来看是这样。你的答案很棒。遗憾的是这个问题不如这个问题好,但我想最好还是作为一个副本结束。

标签: python list dictionary


【解决方案1】:

list() 确实制作了一个副本……但它是一个 副本。当你调用a = list(b) 时,a 是一个全新的列表,但它指的是与b 相同的对象。如果这些对象本身就是列表,那么您还没有做您想做的事情。

要进行“2 级”复制,您可以只使用列表推导:

a = [list(x) for x in b]

要进行全程复制(也可以处理棘手的情况,例如由字符串组成的字符串),请使用 stdlib 中的 deepcopy 函数。


为了调试这些东西,使用is 运算符或id 函数会有所帮助。例如:

>>> list1 = [['x', 'y', 0],
...         ['m', 'n', 0],
... ]
>>> dict2 = {'first': list(list1),
...         'second': list(list1),
... }
>>> id(dict2['first'])
4398414856
>>> id(dict2['second'])
4398414920
>>> id(dict2['first'][0])
4378407688
>>> id(dict2['second'][0])
4378407688

您可以很容易地看到 firstsecond 是两个不同的列表……但它们的第一个元素相同。


或者,或者,在交互式可视化工具中运行您的代码,例如 this one

【讨论】:

  • 您可以通过以下方式确认:print id(dict2['first']), id(dict2['second']); print id(dict2['first'][0]), id(dict2['second'][0]);
  • @Christian:我正在将其编辑为答案; +1 先到那里。
  • 感谢 @abarnert 提供的可视化提示。这真的很整洁,加了书签。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-08
  • 1970-01-01
  • 1970-01-01
  • 2015-08-29
  • 2014-09-07
  • 2017-02-13
相关资源
最近更新 更多