我设置了dict2 = dict1。当我编辑dict2时,原来的dict1也改变了。为什么?
>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1
>>> dict2["key2"] = "WHY?!"
>>> dict1
{'key2': 'WHY?!', 'key1': 'value1'}
我设置了dict2 = dict1。当我编辑dict2时,原来的dict1也改变了。为什么?
>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1
>>> dict2["key2"] = "WHY?!"
>>> dict1
{'key2': 'WHY?!', 'key1': 'value1'}
当前回答
Python中的赋值语句不复制对象,而是在目标和对象之间创建绑定。
因此,dict2 = dict1,结果在dict2和dict1引用的对象之间产生另一个绑定。
如果你想复制字典,你可以使用copy模块。 复制模块有两个接口:
copy.copy(x)
Return a shallow copy of x.
copy.deepcopy(x)
Return a deep copy of x.
浅复制和深复制之间的区别只与复合对象(包含其他对象的对象,如列表或类实例)相关:
浅拷贝构造一个新的复合对象,然后(在可能的范围内)将对原始对象的引用插入其中。
深度复制构造一个新的复合对象,然后递归地将原始对象中的对象的副本插入其中。
例如,在python 2.7.9中:
>>> import copy
>>> a = [1,2,3,4,['a', 'b']]
>>> b = a
>>> c = copy.copy(a)
>>> d = copy.deepcopy(a)
>>> a.append(5)
>>> a[4].append('c')
结果是:
>>> a
[1, 2, 3, 4, ['a', 'b', 'c'], 5]
>>> b
[1, 2, 3, 4, ['a', 'b', 'c'], 5]
>>> c
[1, 2, 3, 4, ['a', 'b', 'c']]
>>> d
[1, 2, 3, 4, ['a', 'b']]
其他回答
虽然dict.copy()和dict(dict1)会生成一个副本,但它们只是浅副本。如果你想要一个深度拷贝,copy.deepcopy(dict1)是必需的。一个例子:
>>> source = {'a': 1, 'b': {'m': 4, 'n': 5, 'o': 6}, 'c': 3}
>>> copy1 = source.copy()
>>> copy2 = dict(source)
>>> import copy
>>> copy3 = copy.deepcopy(source)
>>> source['a'] = 10 # a change to first-level properties won't affect copies
>>> source
{'a': 10, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> copy1
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> copy2
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> copy3
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
>>> source['b']['m'] = 40 # a change to deep properties WILL affect shallow copies 'b.m' property
>>> source
{'a': 10, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> copy1
{'a': 1, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> copy2
{'a': 1, 'c': 3, 'b': {'m': 40, 'o': 6, 'n': 5}}
>>> copy3 # Deep copy's 'b.m' property is unaffected
{'a': 1, 'c': 3, 'b': {'m': 4, 'o': 6, 'n': 5}}
关于浅拷贝和深拷贝,请参阅Python复制模块docs:
浅复制和深复制之间的区别只与复合对象(包含其他对象的对象,如列表或类实例)相关:
浅拷贝构造一个新的复合对象,然后(在可能的范围内)将对原始对象的引用插入其中。 深度复制构造一个新的复合对象,然后递归地将原始对象中的对象的副本插入其中。
下面的代码是在dicts上的,它遵循json语法,比deepcopy快3倍以上
def CopyDict(dSrc):
try:
return json.loads(json.dumps(dSrc))
except Exception as e:
Logger.warning("Can't copy dict the preferred way:"+str(dSrc))
return deepcopy(dSrc)
你可以通过调用带有额外关键字参数的dict构造函数,一次复制和编辑新构造的副本:
>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict(dict1, key2="WHY?!")
>>> dict1
{'key2': 'value2', 'key1': 'value1'}
>>> dict2
{'key2': 'WHY?!', 'key1': 'value1'}
你可以直接使用:
dict2 = eval(repr(dict1))
其中对象dict2是dict1的独立副本,因此可以修改dict2而不影响dict1。
这适用于任何类型的对象。
我遇到了一个奇怪的行为时,试图深度复制类的字典属性w/o赋值给变量
New = copy.deepcopy(my_class.a)不工作,即修改New修改my_class.a
但如果你用old = my_class。A然后new = copy.deepcopy(旧)它工作得很好,即修改new不会影响my_class.a
我不知道为什么会发生这种情况,但希望它有助于节省一些时间!:)