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