复制字典和列表的不同方法

Different methods of copying dicts and lists

在 Python 中,有多种方法可以创建 dict 的浅表副本:有 dict 构造函数、dict.copy 方法和函数 copy 来自 copy 模块:

>>> a = {'a':3, 'b': [1,2,3]}
>>> b = dict(a)
>>> c = a.copy()
>>> from copy import copy
>>> d = copy(a)
>>> a['a'] = 2
>>> a['b'].append(4)
>>> b
{'a': 3, 'b': [1, 2, 3, 4]}
>>> c
{'a': 3, 'b': [1, 2, 3, 4]}
>>> d
{'a': 3, 'b': [1, 2, 3, 4]}
>>> a
{'a': 2, 'b': [1, 2, 3, 4]}

从上面的例子来看,这3种方法似乎都达到了相同的结果。它们的功能是否存在差异?是否应该优先选择其中之一?

对于列表,我们可以使用 l2 = list(l1)l2 = l1.copy()l2 = copy.copy(l1)l2 = l1[:].

来询问类似的问题

如果您希望 dict 变量中发生的任何更新发生在另一个变量上,您可以使用:

dictb=dicta

对可迭代/复合对象(例如列表)或 non-iterable 元素的任何更新都会发生在另一个上。

如果您希望 non-iterable 元素保持完整,您可以复制 element-by-element dict 的内容,或者使用方法 copy()

dictb= dicta.copy()

dictb=copy(dicta)

最后,如果您不想在复制的 dict 中更新两者,请使用 deepcopy()

from copy import deepcopy
dictb=deepcopy(dicta)

至于速度dicta.copy()最快,然后dict(dicta),然后copy(dicta)

简答:它们在功能上是等价的。

文档中没有描述函数之间的差异。检查来源,在许多情况下每个人都会使用相同的功能(dict_merge)。

查看 copy 模块的源代码,copy.copy 调用 dict.copy(以及其他一些 type-specific 复制方法,例如 list.copy,对于那些类型的值)。因此 copy(d)d.copy() 之间的唯一区别是必须知道变量具有 copy 方法才能使用后者。

dict(d) 注释的帮助文档:

dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs

构造函数适用于所有映射类型,而不仅仅是字典。这不会导致功能差异,但可能会因处理更一般的情况而影响性能。但是,检查源代码显示构造函数调用 dict_merge 来处理复制数据,它专门处理 dict,因此底层函数可以应用 case-specific 优化。

dict.copy 调用 PyDict_copy,它自己处理一些特殊情况,但如果有 none 个适用,则调用 dict_merge

总结:就功能而言,使用其中任何一个。如果已知某个值具有 copy 方法(例如,已知它是 dict),则 d.copy() 可能是性能最高的选项。如果不知道值的确切类型但已知它是映射类型,请使用 copy.copy()dict()。如果对类型一无所知,请使用 copy.copy().

list 上的复制操作应该类似,但使用切片 (l1[:]) 可能不会使用相同的底层函数。