Mad*_*ist 737 python dictionary reference python-3.x
有人可以向我解释一下吗?这对我没有任何意义.
我将字典复制到另一个字典中并编辑第二个字典,然后更改两个字典 为什么会这样?
>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1
>>> dict2
{'key2': 'value2', 'key1': 'value1'}
>>> dict2["key2"] = "WHY?!"
>>> dict1
{'key2': 'WHY?!', 'key1': 'value1'}
Run Code Online (Sandbox Code Playgroud)
Mik*_*ham 784
Python 从不隐式复制对象.当你设置时dict2 = dict1
,你正在使它们引用相同的dict对象,所以当你改变它时,对它的所有引用都会继续引用当前状态的对象.
如果你想复制dict(很少见),你必须明确地使用
dict2 = dict(dict1)
Run Code Online (Sandbox Code Playgroud)
要么
dict2 = dict1.copy()
Run Code Online (Sandbox Code Playgroud)
Imr*_*ran 560
当你指定时dict2 = dict1
,你没有复制dict1
,它导致dict2
只是另一个名称dict1
.
要复制的可变类型如字典,使用copy
/ deepcopy
中的copy
模块.
import copy
dict2 = copy.deepcopy(dict1)
Run Code Online (Sandbox Code Playgroud)
gpa*_*nda 135
>>> source = {'a': 1, 'b': {'m': 4, 'n': 5, 'o': 6}, 'c': 3}
>>> copy1 = x.copy()
>>> copy2 = dict(x)
>>> import copy
>>> copy3 = copy.deepcopy(x)
>>> 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}}
Run Code Online (Sandbox Code Playgroud)
Vkr*_*ddy 67
深入而简单的记忆方法:
每当你做 dict2 = dict1 时,dict2 指的是 dict1。dict1 和 dict2 都指向内存中的相同位置。这只是在 python 中处理可变对象时的正常情况。当您在 python 中使用可变对象时,您必须小心,因为它很难调试。
除了使用dict2 = dict1的,你应该用复制(浅复制)和deepcopy的从Python的方法复制模块从dict1单独dict2。
正确的方法是:
>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1.copy()
>>> dict2
{'key1': 'value1', 'key2': 'value2'}
>>> dict2["key2"] = "WHY?"
>>> dict2
{'key1': 'value1', 'key2': 'WHY?'}
>>> dict1
{'key1': 'value1', 'key2': 'value2'}
>>> id(dict1)
140641178056312
>>> id(dict2)
140641176198960
>>>
Run Code Online (Sandbox Code Playgroud)
如您所见,dict1 和 dict2的id不同,这意味着两者都指向/引用内存中的不同位置。
此解决方案适用于具有不可变值的字典,对于具有可变值的字典,这不是正确的解决方案。
例如:
>>> import copy
>>> dict1 = {"key1" : "value1", "key2": {"mutable": True}}
>>> dict2 = dict1.copy()
>>> dict2
{'key1': 'value1', 'key2': {'mutable': True}}
>>> dict2["key2"]["mutable"] = False
>>> dict2
{'key1': 'value1', 'key2': {'mutable': False}}
>>> dict1
{'key1': 'value1', 'key2': {'mutable': False}}
>>> id(dict1)
140641197660704
>>> id(dict2)
140641196407832
>>> id(dict1["key2"])
140641176198960
>>> id(dict2["key2"])
140641176198960
Run Code Online (Sandbox Code Playgroud)
您可以看到,即使我们为 dict1 应用了 copy,但在 dict2 和 dict1 上 mutable 的值都更改为 false,即使我们只在 dict2 上更改它。这是因为我们更改了 dict1 的可变 dict 部分的值。当我们在 dict 上应用副本时,它只会做一个浅拷贝,这意味着它将所有不可变值复制到新的 dict 中,并且不会复制可变值,但会引用它们。
最终的解决方案是对 dict1 进行 deepycopy 以完全创建一个新的 dict,其中复制了所有值,包括可变值。
>>>import copy
>>> dict1 = {"key1" : "value1", "key2": {"mutable": True}}
>>> dict2 = copy.deepcopy(dict1)
>>> dict2
{'key1': 'value1', 'key2': {'mutable': True}}
>>> id(dict1)
140641196228824
>>> id(dict2)
140641197662072
>>> id(dict1["key2"])
140641178056312
>>> id(dict2["key2"])
140641197662000
>>> dict2["key2"]["mutable"] = False
>>> dict2
{'key1': 'value1', 'key2': {'mutable': False}}
>>> dict1
{'key1': 'value1', 'key2': {'mutable': True}}
Run Code Online (Sandbox Code Playgroud)
如您所见,id 不同,这意味着 dict2 是一个全新的 dict,其中包含 dict1 中的所有值。
如果您想在不影响原始字典的情况下更改任何可变值,则需要使用 Deepcopy。如果没有,您可以使用浅拷贝。Deepcopy 很慢,因为它递归地复制原始字典中的任何嵌套值,并且还需要额外的内存。
Pab*_*rre 59
在python 3.5+上,使用**unpackaging运算符可以更轻松地实现浅拷贝.由Pep 448定义.
>>>dict1 = {"key1": "value1", "key2": "value2"}
>>>dict2 = {**dict1}
>>>print(dict2)
{'key1': 'value1', 'key2': 'value2'}
>>>dict2["key2"] = "WHY?!"
>>>print(dict1)
{'key1': 'value1', 'key2': 'value2'}
>>>print(dict2)
{'key1': 'value1', 'key2': 'WHY?!'}
Run Code Online (Sandbox Code Playgroud)
**将字典解压缩到一个新的字典中,然后分配给dict2.
我们还可以确认每个字典都有一个不同的id.
>>>id(dict1)
178192816
>>>id(dict2)
178192600
Run Code Online (Sandbox Code Playgroud)
如果需要深层复制,那么copy.deepcopy()仍然是可行的方法.
AKa*_*ala 45
最好的和最简单的方法创建一个副本一个的字典中都Python的2.7和3是...
要创建简单(单级)字典的副本:
1.使用dict()方法,而不是生成指向现有dict的引用.
my_dict1 = dict()
my_dict1["message"] = "Hello Python"
print(my_dict1) # {'message':'Hello Python'}
my_dict2 = dict(my_dict1)
print(my_dict2) # {'message':'Hello Python'}
# Made changes in my_dict1
my_dict1["name"] = "Emrit"
print(my_dict1) # {'message':'Hello Python', 'name' : 'Emrit'}
print(my_dict2) # {'message':'Hello Python'}
Run Code Online (Sandbox Code Playgroud)
2.使用python字典的内置update()方法.
my_dict2 = dict()
my_dict2.update(my_dict1)
print(my_dict2) # {'message':'Hello Python'}
# Made changes in my_dict1
my_dict1["name"] = "Emrit"
print(my_dict1) # {'message':'Hello Python', 'name' : 'Emrit'}
print(my_dict2) # {'message':'Hello Python'}
Run Code Online (Sandbox Code Playgroud)
要创建嵌套或复杂字典的副本:
使用内置复制模块,该模块提供通用的浅层和深层复制操作.该模块存在于Python 2.7和3中.*
import copy
my_dict2 = copy.deepcopy(my_dict1)
Run Code Online (Sandbox Code Playgroud)
Das*_*hes 35
您也可以使用词典理解来创建一个新词典.这可以避免导入副本.
dout = dict((k,v) for k,v in mydict.items())
Run Code Online (Sandbox Code Playgroud)
当然在python> = 2.7中你可以这样做:
dout = {k:v for k,v in mydict.items()}
Run Code Online (Sandbox Code Playgroud)
但是对于向后兼容,顶级方法更好.
d4r*_*rty 19
除了其他提供的解决方案,您还可以使用**
将字典集成到空字典中,例如,
shallow_copy_of_other_dict = {**other_dict}
.
现在你将有一个"浅"的副本other_dict
.
适用于您的示例:
>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = {**dict1}
>>> dict2
{'key1': 'value1', 'key2': 'value2'}
>>> dict2["key2"] = "WHY?!"
>>> dict1
{'key1': 'value1', 'key2': 'value2'}
>>>
Run Code Online (Sandbox Code Playgroud)
小智 17
Python中的赋值语句不复制对象,它们在目标和对象之间创建绑定.
所以,dict2 = dict1
它会导致dict2
与dict1
引用的对象之间的另一个绑定.
如果你想复制一个字典,你可以使用copy module
.复制模块有两个界面:
copy.copy(x)
Return a shallow copy of x.
copy.deepcopy(x)
Return a deep copy of x.
Run Code Online (Sandbox Code Playgroud)
浅复制和深复制之间的区别仅与复合对象(包含其他对象的对象,如列表或类实例)相关:
甲浅拷贝构造新化合物对象,然后(在可能的范围)插入到其在原始找到的对象的引用.
甲深层副本构造新化合物的对象,然后,递归地,插入拷贝到它在原始找到的对象的.
例如,在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')
Run Code Online (Sandbox Code Playgroud)
结果是:
>>> 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']]
Run Code Online (Sandbox Code Playgroud)
Fre*_*abe 10
您可以通过dict
使用其他关键字参数调用构造函数来一次复制和编辑新构建的副本:
>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict(dict1, key2="WHY?!")
>>> dict1
{'key2': 'value2', 'key1': 'value1'}
>>> dict2
{'key2': 'WHY?!', 'key1': 'value1'}
Run Code Online (Sandbox Code Playgroud)
最初,这让我很困惑,因为我来自C背景.
在C中,变量是内存中具有已定义类型的位置.分配给变量会将数据复制到变量的内存位置.
但在Python中,变量更像是指向对象的指针.因此,将一个变量分配给另一个变量不会产生副本,它只会使该变量名称指向同一个对象.
在python(东西每个变量像dict1
或str
或__builtins__
是一个指向设备内部的一些隐藏柏拉图"对象".
如果你设置dict1 = dict2
,你只需指向dict1
相同的对象(或内存位置,或任何你喜欢的类比)dict2
.现在,引用的对象与引用的对象dict1
相同dict2
.
你可以检查:dict1 is dict2
应该True
.另外,id(dict1)
应该是一样的id(dict2)
.
你想要的dict1 = copy(dict2)
,或者dict1 = deepcopy(dict2)
.
copy
与deepcopy
?之间的区别?deepcopy
将确保dict2
(您是否将其指向列表?)的元素也是副本.
我没有deepcopy
太多使用- 编写需要它的代码通常是不好的做法(在我看来).
小智 6
>>> dict2 = dict1
# dict2 is bind to the same Dict object which binds to dict1, so if you modify dict2, you will modify the dict1
Run Code Online (Sandbox Code Playgroud)
复制Dict对象的方法有很多种,我简单的用
dict_1 = {
'a':1,
'b':2
}
dict_2 = {}
dict_2.update(dict_1)
Run Code Online (Sandbox Code Playgroud)
dict1
是引用基础字典对象的符号.分配dict1
给dict2
仅仅分配相同的参考.通过dict2
符号更改键的值会更改基础对象,这也会影响dict1
.这令人困惑.
推理不可变值比引用要容易得多,所以尽可能复制:
person = {'name': 'Mary', 'age': 25}
one_year_later = {**person, 'age': 26} # does not mutate person dict
Run Code Online (Sandbox Code Playgroud)
这在语法上与以下相同:
one_year_later = dict(person, age=26)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
523970 次 |
最近记录: |