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 dict
s 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.