[Tutor] question about __copy__ and __deepcopy__

Albert-Jan Roskam sjeik_appie at hotmail.com
Thu Apr 14 15:38:31 EDT 2016


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. So I implemented __copy__ and __deepcopy__,
Is this the correct way to do this? In my original use case, even shallow copies failed, but I can't reproduce that anymore (or maybe I am imagining things!). 
Is __copy__ really needed here? Does __deepcopy__ make any sense at all? My tests pass, but still I am not sure!

Thanks!

Albert-Jan

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())]
        return "{" + ", ".join(items) + "}"

    def __copy__(self):
        return Record(**self.__dict__.copy())

    def __deepcopy__(self, memo):
        address = id(self)
        try:
            return memo[address]
        except KeyError:
            memo[address] = {k: copy(v) for k, v in self.items()}
            return deepcopy(self, memo)

if __name__ == "__main__":
    
    # only shallow needed        
    record = Record(x=1, y=2, z=3)
    cp = copy(record)
    assert record == cp and not record is cp
    record = Record(x=1, y=2, z=3)
    dc = deepcopy(record)
    assert record == dc and not record is dc
    
    # mutable value: deepcopy needed
    L = range(10)
    record = Record(x=1, y=2, z=L)
    cp = copy(record)
    print record, cp
    assert record == cp and not record is cp
    dc = deepcopy(record)
    assert record == dc and not record is dc
    L.insert(0, 42)
    expect = {'y': 2, 'x': 1, 'z': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}
    assert dc == expect and not record is dc
    print record, dc
        
 		 	   		  


More information about the Tutor mailing list