Implementing deepcopy

Alex Martelli aleax at mail.comcast.net
Wed Dec 7 22:39:14 EST 2005


Mr.Rech <andrea.riciputi at gmail.com> wrote:
   ...
> Suppose one of the attributes of my class is a dictionary whose values
> are callable functions, such as:
> 
> >>>def foo():
> .....    pass
> >>>def bar():
> .....    pass
> 
> >>>adict = dict(a = foo, b = bar)
> 
> Now if I try:
> 
> >>> anotherdict = copy.deepcopy(adict)   # It doesn't work

Right, because functions are not copyable (although you could, if you
wished, write a way to copy them and copy_reg it).

> however:
> 
> >>> anotherdict = copy.copy(adict)     # works as expected

Right, as it's a shallow copy.


> My question is: anotherdict is really a copy of adict? If so, what is
> the difference between its definition and the following:
> 
> >>> yanotherdict = dict(adict)

No difference whatsoever, and in fact

>>> guesswhat = adict.copy()

is yet another way to do just the same thing -- a shallow copy.

The use of copy.copy(foo) is recommended when you aren't sure what type
you're dealing with in 'foo', but want the same identical type as a
result; the use of dict(foo) is recommended when you aren't sure what
type you're dealing with in 'foo', but want a dict as a result.

If you're certain you're dealing with a dict, then, if this code is
critical for your app's performance, pick the fastest way.  Use timeit
to find the fastest way, e.g., on my iBook:

Helen:~ alex$ python -mtimeit -s'd=dict.fromkeys(range(99))' -s'import
copy' 'copy.copy(d)'
100000 loops, best of 3: 17.3 usec per loop
Helen:~ alex$ python -mtimeit -s'd=dict.fromkeys(range(99))' -s'import
copy' 'd.copy()'
100000 loops, best of 3: 11.4 usec per loop
Helen:~ alex$ python -mtimeit -s'd=dict.fromkeys(range(99))' -s'import
copy' 'dict(d)'
100000 loops, best of 3: 12.8 usec per loop
Helen:~ alex$ 

I would avoid copy.copy (measurably slower) and end up using (as I
usually do...) dict(d), but I wouldn't bitch against anybody choosing to
use d.copy() instead for a 10%-or-so gain in speed.

Personally, I find that list(L), dict(D), set(S) and so on are the best
way to perform shallow copies for known-type objects, and strongly
dislike type-specific divergences such as L[:] and D.copy() and
S.copy(), but there's no community consensus on this point.


Alex



More information about the Python-list mailing list