> Date: Fri, 15 Apr 2016 16:30:16 +1000 > From: st...@pearwood.info > To: tutor@python.org > Subject: Re: [Tutor] question about __copy__ and __deepcopy__ > > On Thu, Apr 14, 2016 at 07:38:31PM +0000, Albert-Jan Roskam wrote: > > Hi, > > > > Lately I have been using the "mutable namedtuple" shown below a lot. > > I found it somewhere on StackOverflow or ActiveState or something. In > > its original form, it only had an __init__ method. I noticed that > > copying Record objects sometimes failed. > > Failed how? > > Given how simple the class looks, I wonder whether that's a bug in copy. > Apart from a fancy __str__ method, there's practically nothing to it! > > So I took your Record class, stripped out the __copy__ and __deepcopy__ > methods, created a slightly complex instance, and tried copying it: > > d = Record(spam=23, ham=42, eggs=[], cheese={}) > d.cheese[1] = None > d.cheese[2] = ['a', 'b', 'c'] > d.eggs.append(100) > d.eggs.append(200) > d.eggs.append(d) > d.eggs.append(d.cheese) > > from copy import copy, deepcopy > > copy(d) > deepcopy(d) > > > and both appeat to work correctly. So perhaps you ought to look more > carefully at the copying failure?
Hi Steven, Heh, it's my fancy __str__ method that confused me. This is what I get when I run my code without __copy__ and __deepcopy__ runfile('/home/albertjan/Downloads/attrdict_tutor.py', wdir='/home/albertjan/Downloads') {'x': 1, 'y': 2, 'z': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]} {'x': 1, 'y': 2, 'z': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]} {'x': 1, 'y': 2, 'z': [42, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]} {} # print statements --> call __str__ dc.__str__() Out[19]: '{}' dc.__repr__() Out[20]: "{'y': 2, 'x': 1, 'z': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}" Wicked. I do not understand the output of dc.__str__(). Somehow self.__dict__ is empty. If I store a deepcopy of the instance __dict__ in a class attribute "Record.dict_copy", __str__ does not return just the two curly braces. It's wasteful to create a copy, though. from copy import copy, deepcopy class Record(dict): def __init__(self, *args, **kwargs): super(Record, self).__init__(*args, **kwargs) self.__dict__ = self def __str__(self): #items = ["%r: %r" % (k, v) for k, v in sorted(self.__dict__.items())] Record.dict_copy = deepcopy(self) # store it as a class attribute. items = ["%r: %r" % (k, v) for k, v in sorted(Record.dict_copy.items())] return "{" + ", ".join(items) + "}" runfile('/home/albertjan/Downloads/attrdict_tutor.py', wdir='/home/albertjan/Downloads') {'x': 1, 'y': 2, 'z': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]} {'x': 1, 'y': 2, 'z': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]} {'x': 1, 'y': 2, 'z': [42, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]} {'x': 1, 'y': 2, 'z': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]} dc.__str__() Out[28]: "{'x': 1, 'y': 2, 'z': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}" dc.__repr__() Out[29]: "{'y': 2, 'x': 1, 'z': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}" _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor