Assume we have a simple Python dictionary:
dict_ = {'foo': 1, 'bar': 2}开发者_如何学运维
Which is the better way to copy this dictionary?
copy1 = dict(dict_)
copy2 = dict_.copy()
Is there a compelling reason to favour one approach over the other?
I always use the dict
constructor: it makes it obvious that you are creating a new dict
whereas calling the copy
method on an object could be copying anything. Similarly for list
I prefer calling the constructor over copying by slicing.
Note that if you use subclasses of dict
using the copy
method can get confusing:
>>> from collections import defaultdict
>>> d = defaultdict(int)
>>> d['a']
0
>>> d.copy()
defaultdict(<class 'int'>, {'a': 0})
>>> dict(d)
{'a': 0}
>>>
The copy
method of defaultdict
gives you another defaultdict
, but unless you override copy
in a subclass the default action is just to give you a dict
:
>>> class MyDict(dict): pass
>>> d = MyDict(a=1)
>>> d
{'a': 1}
>>> type(d)
<class '__main__.MyDict'>
>>> type(d.copy())
<class 'dict'>
That means you have to know about the internal details of a subclass to know what type the copy
method will return.
One could favor option #1 (dict(dict_)
) because of the principle of least surprise: you can do the same for lists: list(list_)
, and lists don't have a copy()
method.
That said, many good points were raised in the answers. This indicates that there might not be any obviously better solution, and that both are fine, as long as you do what you intend to do (the point about subclassing dict
might be crucial, in some codes, for instance). So, I would just choose whatever feels right for your application given the points raised in the responses!
It really depends... on what you actually intend to use it for. In library, you may need to mutate a copy of some dict-like object, and you want a copy that is the same object. Other APIs must have an actual dict
, so would create a new dict
with the constructor method and use that one. But you lose the actual original type information (and methods) when you do that. But overall, I would prefer the copy() method as it is clear it is a copy of of a dict-like object (not just a dict). That makes it more flexible (duck typing).
The best would be dict_.copy()
since the intention is self-descriptive. However, using the dict
form you can create a copy with extra keys:
d = dict(a, zoo=1, zar=2)
which is equivalent, but shorter than:
d = a.copy()
d.update(zoo=1, zar=2)
Second one is better because it explicitly
shows you are copy
'ing.
I don’t like the dict.copy()
method:
- it’s not clear from the name what kind of copy
.copy()
does - subclasses have to overwrite it, or it’s semantic is completely hosed
- shallow copies can be done by other ways (the general
copy.copy()
ordict()
)
Imagine a random class, e.g. Uber
. – How would you try to make a copy of u = Uber(...)
?
dict(u)
Uber(u)
u.copy()
copy.copy(u)
I would say that number 2. has the highest chances to work —or— to blow up. – Exactly what I want.
精彩评论