Python 词典的深度副本创建时理解不起作用
您能帮助我理解为什么Python 词典的深度副本创建时理解不起作用,python,deep-copy,dictionary-comprehension,Python,Deep Copy,Dictionary Comprehension,您能帮助我理解为什么deepcopy不能适用于下面示例中字典中的所有元素吗 import copy a = [{'id':1, 'list':[1,2,3], 'num':3}, {'id':2,' list':[4,5,6], 'num':65}] b = {i['id']:copy.deepcopy(i) for i in a} In [1]: print(id(a) == id(b))
deepcopy
不能适用于下面示例中字典中的所有元素吗
import copy
a = [{'id':1, 'list':[1,2,3], 'num':3}, {'id':2,' list':[4,5,6], 'num':65}]
b = {i['id']:copy.deepcopy(i) for i in a}
In [1]: print(id(a) == id(b))
Out[1]: False
In [2]: print(id(a[0]) == id(b[1]))
Out[2]: False
In [3]: print(id(a[0]['list']) == id(b[1]['list']))
Out[3]: False
In [4]: print(id(a[0]['num']) == id(b[1]['num']))
Out[4]: True
特别是,与'num'
键相关联的值是相同的,而'list'
键的值似乎已通过深度复制成功复制。我猜这与存储的值的数据类型有关,有人能给我指出正确的方向吗
谢谢 python中可变类型和不可变类型之间有很大的区别。
通常,Python中的变量类型包括列表、字典和集合。不可变类型包括字符串、int、float和元组。
重新分配不可变类型的变量实际上是重新创建不可变类型的对象,并将原始变量重新指向新创建的对象(打开一个新的内存地址),如果没有其他变量引用原始对象(即引用计数为0),原始对象将被回收。python中可变类型和不可变类型之间有很大的区别。
通常,Python中的变量类型包括列表、字典和集合。不可变类型包括字符串、int、float和元组。
重新分配不可变类型的变量实际上是重新创建不可变类型的对象,并将原始变量重新指向新创建的对象(打开一个新的内存地址),如果没有其他变量引用原始对象(即引用计数为0),原始对象将被回收。这与dict理解无关,但正如您所建议的,与数据类型有关:
>>> import copy
>>> x = 1
>>> copy.deepcopy(x) is x
True
>>> x = [1]
>>> copy.deepcopy(x) is x
False
@mengban的区别是正确的:您有可变和不可变的对象(这取决于对象的类型)。不可变对象的典型示例有:整数(0
,1
,2
)、浮点数(3.14159
),还有字符串(“foo”
)和元组((1,3)
)。可变对象的典型示例有:列表([1,2,3]
)或字典({'a':1,'b':2}
)
基本上,不可变对象的deepcopy
返回对象本身:不执行实际的复制(元组有一个小技巧:我稍后会解释):
可变对象的deepcopy
创建具有相同元素的对象的新实例
这是正确的行为,因为当您获得对象的深度副本时,合同规定这是您的副本。在o
上执行的任何操作都不能修改o2
。如果o
是不可变的,则免费保证。但是如果o
是可变的,那么您需要创建一个具有相同内容的新实例(这意味着一个递归深度副本)
现在元组怎么了
>>> o = ([1], [2])
>>> copy.deepcopy(o) is o
False
即使元组本身是不可变的,它的一个元素也可能是可变的。如果我给你一个对o
(即o2=o
)值的引用o2
,你可以写o2[0]。附加(10)
,我的对象o
被修改。因此,deepcopy
函数在元组中查找可变对象,并决定是否需要实际副本
奖励:看一看。\u deepcopy\u dispatch
将类型映射到实际的复印机:
_deepcopy_dispatch = d = {}
...
d[int] = _deepcopy_atomic
d[float] = _deepcopy_atomic
d[bool] = _deepcopy_atomic
...
d[str] = _deepcopy_atomic
...
d[list] = _deepcopy_list
...
d[tuple] = _deepcopy_tuple
...
d[dict] = _deepcopy_dict
...
虽然\u deepcopy\u atomic
只返回值,\u deepcopy\u list
,\u deepcopy\u tuple
,\u deepcopy\u dict
。。。通常进行深入复制
您可以检查以了解流程。基本上,深度复制每个元素,直到实际复制完成。如果创建了副本,则创建一个新的深度副本元组。否则返回初始元组。这与dict理解无关,但正如您所建议的,与数据类型有关:
>>> import copy
>>> x = 1
>>> copy.deepcopy(x) is x
True
>>> x = [1]
>>> copy.deepcopy(x) is x
False
@mengban的区别是正确的:您有可变和不可变的对象(这取决于对象的类型)。不可变对象的典型示例有:整数(0
,1
,2
)、浮点数(3.14159
),还有字符串(“foo”
)和元组((1,3)
)。可变对象的典型示例有:列表([1,2,3]
)或字典({'a':1,'b':2}
)
基本上,不可变对象的deepcopy
返回对象本身:不执行实际的复制(元组有一个小技巧:我稍后会解释):
可变对象的deepcopy
创建具有相同元素的对象的新实例
这是正确的行为,因为当您获得对象的深度副本时,合同规定这是您的副本。在o
上执行的任何操作都不能修改o2
。如果o
是不可变的,则免费保证。但是如果o
是可变的,那么您需要创建一个具有相同内容的新实例(这意味着一个递归深度副本)
现在元组怎么了
>>> o = ([1], [2])
>>> copy.deepcopy(o) is o
False
即使元组本身是不可变的,它的一个元素也可能是可变的。如果我给你一个对o
(即o2=o
)值的引用o2
,你可以写o2[0]。附加(10)
,我的对象o
被修改。因此,deepcopy
函数在元组中查找可变对象,并决定是否需要实际副本
奖励:看一看。\u deepcopy\u dispatch
将类型映射到实际的复印机:
_deepcopy_dispatch = d = {}
...
d[int] = _deepcopy_atomic
d[float] = _deepcopy_atomic
d[bool] = _deepcopy_atomic
...
d[str] = _deepcopy_atomic
...
d[list] = _deepcopy_list
...
d[tuple] = _deepcopy_tuple
...
d[dict] = _deepcopy_dict
...
虽然\u deepcopy\u atomic
只返回值,\u deepcopy\u list
,\u deepcopy\u tuple
,\u deepcopy\u dict
。。。通常进行深入复制
您可以查看以了解