列表和词典的浅层和深层副本

时间:2014-12-23 20:54:15

标签: python deep-copy shallow-copy

我正在尝试更好地理解Python中的浅层和深层副本,尤其是涉及字典和列表时。

假设我有一个词典列表,我想将特定键('a')的值复制到不同键名('x')下的不同词典列表中:

list_dict = [{'a': 1}, {'a': 2}]

dict1 = {}
dict1['x'] = {}
list1 = []

for entry in list_dict:
    dict1['x'] = entry['a']
    list1.append(dict1)

>>>print list1
[{'x': 2}, {'x': 2}]

显然,不是我想要的。但是,我知道我可以为字典指定.copy()来创建浅拷贝:

for entry in list_dict:
    dict1['x'] = entry['a']
    list1.append(dict1.copy())

>>>print list1
[{'x': 1}, {'x': 2}]

即使它很浅,也可以。现在,让它变得有点不同 - 我想将其复制到dict1['x'],而不是dict1['x']['y']

for entry in list_dict:
    dict1['x']['y'] = entry['a']
    list1.append(dict1.copy())

>>>print list1
[{'x': {'y': 2}}, {'x': {'y': 2}}]

回到原点 - 它不起作用!那么,这是第一个问题 - 它为什么停止工作?

第二个问题是,为什么添加最后一行会使其有效?

for entry in list_dict:
    dict1['x']['y'] = entry['a']
    list1.append(dict1.copy())
    dict1['x'] = {}

>>>print list1
[{'x': {'y': 1}}, {'x': {'y': 2}}]

非常感谢你!

P.S。我知道我可以import copy然后copy.deepcopy(),但是我有兴趣了解为什么当我添加更多级别的字典时浅层副本停止工作,为什么&的解决方法#34;复位"字典工作。

1 个答案:

答案 0 :(得分:2)

for entry in list_dict:
    dict1['x']['y'] = entry['a']
    list1.append(dict1.copy())

>>>print list1
[{'x': {'y': 2}}, {'x': {'y': 2}}]

回到原点 - 它不起作用!所以,这是第一个问题 - 它为什么停止工作?

因为,您现在有三个词典:

  1. {'x': {'y': 2}}
  2. {'x': {'y': 2}}
  3. {'y': 2}

    其中只有两个是"复制" (1和2)。它们都是引用3. 3中的变化反映在1和2中。


  4. 第二个问题是,为什么添加最后一行会使其有效?

    for entry in list_dict:
        dict1['x']['y'] = entry['a']
        list1.append(dict1.copy())
        dict1['x'] = {}
    
    >>>print list1
    [{'x': {'y': 1}}, {'x': {'y': 2}}]
    

    因为,您现在正在每次迭代(使用{})创建新词典,然后进行更改。您已在初始化代码中创建了第一个。您没有更改列表中旧词典的引用。只有即将插入的那个。

    未来提示:在这种情况下,为了帮助您遵循代码,最好的办法是使用调试模式并逐步执行程序。或者做懒人做的事情,在迭代过程中简单地在对象内打印,看看他们的价值是什么。