[Tutor] question about __copy__ and __deepcopy__
Oscar Benjamin
oscar.j.benjamin at gmail.com
Fri Apr 15 05:31:53 EDT 2016
On 15 April 2016 at 09:55, Albert-Jan Roskam <sjeik_appie at hotmail.com> wrote:
>
> 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.
This kind of confusion comes from setting self.__dict__ = self. That's
not really a normal thing to do so I wouldn't expect it to necessarily
be supported by other things like copy.copy:
In [1]: class Record(dict):
...: def __init__(self, *args, **kwargs):
...: super(Record, self).__init__(*args, **kwargs)
...: self.__dict__ = self
...:
In [2]: r = Record(x=1, y=2)
In [3]: r
Out[3]: {'x': 1, 'y': 2}
In [4]: r.__dict__ is r # <--- Compare with r2 below
Out[4]: True
In [5]: import copy
In [6]: r2 = copy.copy(r)
In [7]: r2
Out[7]: {'x': 1, 'y': 2}
In [8]: r2.__dict__
Out[8]: {'x': 1, 'y': 2}
In [9]: r2 is r2.__dict__ # <-- self.__dict__ is not self
Out[9]: False
In [13]: type(r2.__dict__)
Out[13]: dict
In [14]: type(r.__dict__)
Out[14]: __main__.Record
In [15]: r2.__dict__ == r.__dict__ # <-- Equal but distinct
Out[15]: True
--
Oscar
More information about the Tutor
mailing list