I am trying to avoid repeating the same code in the clone methods of two classes, one inheriting from the other. My current approach is to put the code that is common to both classes in the (non-static) clone method of the base class and call it from the extending class. To do this I am trying to pass the constructor of the extending class to the base class so it can be invoked there. Here is a simplified example of what I am currently doing:
class S(object):
"""Base class"""
def __init__(self):
self.a = 0
def clone(self, constructor=None):
if constructor is None:
constructor = self.__init__
cloned = constructor()
# Expecting: cloned.a = 1, cloned.b = 7
assert cloned is not None # raises AssertionError
cloned.a = self.a # Set a to 2
return cloned
class C(S):
"""Child class, extending Base"""
def __init__(self):
self.a = 1
self.b = 7
def clone(self):
cloned = super(C, self).clone(self.__init__)
# Expecting: cloned.a = 2, cloned.b = 7
cloned.b = self.b # Set b to 8
return cloned
if __name__ == '__main__':
c1 = C()
c1.a = 2
c1.a = 8
c2 = c1.clone()
My questions at this point are:
-
Why is
Nonereturned when calling theclonemethod of the base class? -
Do I have to bind the method to a class in order to use it, using
types.MethodTypeor__get__? -
What would you suggest as a better way to go?
While
__init__()is often called the constructor in Python, it actually isn’t. It gets the instance passed in as theselfargument, and it returnsNone. The instance is constructed earlier by the__new__()method, which is the actual constructor. You shouldn’t pass in a reference to__new__, though. It’s much easier and more straightforward to pass in the type itself.Edit: The right approach to implement a
clonemethod is yet another one: Stick to the usual Python protocols, and implement__getstate__()and__setstate__()on your instances. Then you can use the functions from thecopymodule to clone your instances correctly.