Implementing deepcopy

Discussion in 'Python' started by Mr.Rech, Dec 7, 2005.

  1. Mr.Rech

    Mr.Rech Guest

    Hi all,
    I'm writing a class with some attributes which deepcopy can't cope
    with, and I need some more clarifications. Sorry for my newbie
    questions, but I'm a newbie indeed (or a sort of).

    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


    however:

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


    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)


    ??

    Thanks in advance,
    Andrea.
    Mr.Rech, Dec 7, 2005
    #1
    1. Advertising

  2. Mr.Rech <> 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
    Alex Martelli, Dec 8, 2005
    #2
    1. Advertising

  3. Mr.Rech

    Mr.Rech Guest

    Thanks for your answer. Since perfomances are not an issue in my case I
    think I'd stay with copy.copy(). In this way I'm not required to know
    in advance the object type, and I can implement a __deepcopy__ method
    for my own classes as follows:

    >>> def __deepcopy__(self, memo = {}):

    new = self.__class__.__new__(self.__class__)
    memo[id(self)] = new
    for key, val in self.__dict__.iteritems():
    try:
    setattr(new, key, copy.deepcopy(val, memo))
    except TypeError:
    setattr(new, key, copy.copy(val))
    return new

    The method is quite general (at least I hope so), and can be easily
    inherited by all the subclasses without any major change. Is that
    right? Am I missing something here? Any better way to implement this?

    Thanks again,
    Andrea
    Mr.Rech, Dec 8, 2005
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    0
    Views:
    610
  2. Eugeni Doljenko

    Legitimacy of deepcopy

    Eugeni Doljenko, Jun 4, 2004, in forum: Python
    Replies:
    2
    Views:
    313
    David Bolen
    Jun 7, 2004
  3. Donnal Walter

    deepcopy in new-style classes

    Donnal Walter, Jun 22, 2004, in forum: Python
    Replies:
    0
    Views:
    250
    Donnal Walter
    Jun 22, 2004
  4. OKB (not okblacke)

    deepcopy raises TypeError for method/function?

    OKB (not okblacke), Sep 9, 2004, in forum: Python
    Replies:
    3
    Views:
    383
    Alex Martelli
    Sep 10, 2004
  5. Dan Perl
    Replies:
    0
    Views:
    312
    Dan Perl
    Sep 14, 2004
Loading...

Share This Page