Semi-newbie, rolling my own __deepcopy__

Steven Bethard steven.bethard at gmail.com
Wed Apr 6 10:55:45 EDT 2005


ladasky at my-deja.com wrote:
> Michael Spencer wrote:
> 
>>ladasky at my-deja.com wrote:
> 
> [snip]
> 
>>>Anyway, my present problem is that I want to make copies of
> 
> instances
> 
>>>of my own custom classes.  I'm having a little trouble
> 
> understanding
> 
>>>the process.  Not that I think that it matters -- but in case it
> 
> does,
> 
>>>I'll tell you that I'm running Python 2.3.4 on a Win32 machine.
> 
> [snip]
> 
>>If you google for:
>>  python __deepcopy__ cookbook
>>you will find a couple of examples of this method in use, among them:
> 
> 
>>http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/259179
>>
>> 1  class deque(object):
>> 2
>> 3      def __init__(self, iterable=()):
>> 4          if not hasattr(self, 'data'):
>> 5              self.left = self.right = 0
>> 6              self.data = {}
>> 7          self.extend(iterable)
>>
>>[...snip methods...]
>>
>> 8    def __deepcopy__(self, memo={}):
>> 9        from copy import deepcopy
>>10        result = self.__class__()
>>11        memo[id(self)] = result
>>12        result.__init__(deepcopy(tuple(self), memo))
>>13        return result
>>
> So, entering deepcopy, I encounter the first new concept (for me) on
> line 10.  We obtain the class/type of self.  On line 11 we create a
> dictionary item in memo, [id(self):type(self)].  So now I'm confused as
> to the purpose of memo.  Why should it contain the ID of the *original*
> object?

Note that you obtain *and then call* the class/type of self:

py> i, s = 100, 'string'
py> i.__class__, s.__class__
(<type 'int'>, <type 'str'>)
py> i.__class__(), s.__class__()
(0, '')

So you've created a new object calling the constructor with no 
arguments.  So 'result' is a new instance of the class.

> Things get even stranger for me on line 12.  Working from the inside of
> the parentheses outward, an attempt is made to convert self to a tuple.
>  Shouldn't this generate a TypeError when given a complex, non-iterable
> item like the deque class?  I just tried running one of my programs,
> which assigns the name "x" to one of my custom objects, and when I
> execute tuple(x), a TypeError is what I get.

tuple(x) works on any object that defines __iter__:

py> class C(object):
...     def __iter__(self):
...         yield 1
...         yield 2
...         yield 5
...
py> tuple(C())
(1, 2, 5)

So line 12 is making a tuple of the values in the object, and then 
calling result's __init__ again, this time with (a deepcopied) tuple as 
an argument.  This adds the content to the previously uninitialized object.

HTH,

STeVe



More information about the Python-list mailing list