Is there a decent way of creating a copy constructor in python?

carmenism picture carmenism · May 17, 2012 · Viewed 12.7k times · Source

I realize questions quite similar to this have been asked, though not exactly this way.

I'd like to have an optional argument for the constructor of my class that, if it is an instance of my class, will be copied. For example, something like (I know this code does not work!):

class Foo(object):
    def __init__(self, foo=None):
        self.x = None
        self.y = None
        self.z = None

        if foo is not None and isinstance(foo, Foo):
            self = copy.deepcopy(foo)

a = Foo()
a.x = 1
a.y = 2
a.z = 3

b = Foo(a)
print b.x
print b.y
print b.z

I know there are a few practical solutions to this. I could set each attribute of self according to the value of foo's corresponding attribute, but this would be really annoying because my class has many, many attributes. Or I could simply use do:

b = copy.deepcopy(a)

...But I'd rather not if that is possible. I'm also hoping to avoid overriding __new__.

Is there really no decent way at all in python to create a copy constructor?

Answer

Nick Craig-Wood picture Nick Craig-Wood · May 17, 2012

I think this is the most pythonic way of doing it - a copy factory method.

import copy

class Foo(object):
    def __init__(self):
        self.x = None
        self.y = None
        self.z = None
    def copy(self):
        return copy.deepcopy(self)

a = Foo()
a.x = 1
a.y = 2
a.z = 3

b = a.copy()
print b.x
print b.y
print b.z

This is fairly common in python basic types (eg dict.copy). It is not a copy constructor, but I don't think that is a very pythonic concept!