In Python there are various ways to create a shallow copy of a dict: there's the dict constructor, the dict.copy method, and the function copy from the copy module:
>>> 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]}
From the above example, all these 3 methods seem to achieve the same result. Is there a difference in their functionality and should one of them be preferred over the others?
A similar question could be asked for lists, where we can use l2 = list(l1), l2 = l1.copy(), l2 = copy.copy(l1) or l2 = l1[:].
CodePudding user response:
If you want any update occurring in the dict variable to happen to the other one you can use:
dictb=dicta
Any update to an iterable / compound object(e.g. a list) or a non-iterable element will happen to the other.
If you want the non-iterable element to stay intact, you can either copy the element-by-element the content of the dict, or use the method copy()
dictb= dicta.copy()
or
dictb=copy(dicta)
Finally, if you want neither to be updated in the copied dict use deepcopy()
from copy import deepcopy
dictb=deepcopy(dicta)
As for the speed dicta.copy() is the fastest, then dict(dicta), then copy(dicta)
CodePudding user response:
Short answer: they are functionally equivalent.
No differences between the functions are described in the documentation. Examining the source, each will use the same function (dict_merge) in many cases.
Looking at the source of the copy module, copy.copy calls dict.copy (as well as a few other type-specific copy methods, such as list.copy, for values of those types). Thus the only difference between copy(d) and d.copy() is that a variable must be known to have a copy method to use the latter.
The help doc for dict(d) notes:
dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs
The constructor works on all mapping types, not just dicts. This won't cause functional differences, but could impact performance due to handling a more general case. However, examining the source shows the constructor calls dict_merge to handle copying the data, which handles dicts specially, so the underlying function can apply case-specific optimizations.
dict.copy calls PyDict_copy, which handles a few special cases itself but calls dict_merge if none of those apply.
In summary: in terms of functionality, use any of them. If a value is known to have a copy method (e.g. it's known to be a dict), d.copy() will likely be the most performant option. If the exact type of a value isn't known but it's known to be a mapping type, use copy.copy() or dict(). If nothing is known about the type, use copy.copy().
Copy operations on list should be similar, though using a slice (l1[:]) may not use the same underlying function.
