Multiple constructors in python using inheritance

I have an AbstractDataHandle class, with its init method and class classifier. I would like to have two constructors in Classifier, for example Java. One is inherited from its superclass and one new.

This will be something like (but I intend to “save” the two constructors):

class AbstractDataHandle(): def __init__(self, elements, attributes, labels): self._load(elements, attributes, labels) class Classifier(AbstractDataHandle): def __init__(self, classifier="LinearSVC", proba=False): self._fit(classifier, proba) 

Can I have two constructors in the same class? If so, can I have a constructor inherited from the superclass and add a new one?

Thanks in advance.

+11
python inheritance constructor oop
Oct 10 '13 at 20:11
source share
3 answers

You cannot have two constructors in the same class.

Constructors should be named __init__ . And, unlike Java, Python does not allow overloading functions or methods by the type of their arguments. So, if you had two constructors, they would both be the same function.

There are several ways around this.




Use @classmethod as alternative constructors:

 class Breakfast(object): @classmethod def from_eggs(cls, eggs): obj = cls() obj.spam, obj.eggs = 5, eggs return obj @classmethod def from_spam_and_eggs(cls, spam, eggs): obj = cls() obj.spam, obj.eggs = spam, eggs return obj 

A simple example from the standard library is datetime.datetime , which can be built using now , fromtimestamp or several other alternative constructors besides the default .




Use the default parameters, keywords and / or variable arguments to create one constructor, which can be called in different ways:

 class Breakfast(object): def __init__(self, eggs=0, spam=5): self.spam, self.eggs = spam, eggs 

int is an example of this: you can create it from a string and a base, or from a single argument that knows how to convert itself to an integer.




Create subclasses, each of which has different constructors:

 class Breakfast(object): pass class HealthyBreakfast(object): def __init__(self, spam): self.spam, self.eggs = spam, 0 class NormalBreakfast(object): def __init__(self, spam, eggs): self.spam, self.eggs = spam, eggs 



In either of these cases, you can split the commonalities into one “base” initializer. For example:

 class Breakfast(object): def __init__(self, eggs, spam): self.spam, self.eggs = spam, eggs class HealthyBreakfast(object): def __init__(self, spam): super(HealthyBreakfast, self).__init__(0, spam) 



Of course, in no case should you eat breakfast without spam.

+38
Oct 10 '13 at 20:19
source share

You can use class methods that work like factory methods. This is the best approach for multiple designers. The first argument to 'cls' is the class itself, not the instance, so cls ('Truck') in the class method calls the constructor for the Car class.

 class Car(object): def __init__(self, type='car'): self.car_type = type @classmethod def Truck(cls): return cls('Truck') @classmethod def Sport(cls): return cls('Sport') @classmethod def Van(cls): return cls('Van') 

Then you call the factory method as follows:

 mycar = Car.Sport() 
+3
Oct 10 '13 at 20:26
source share

There are methods in the accepted answer, but I think it is quite flexible. It is confusing, but very flexible.

When the class is initiated, init calls the method and passes it a string argument (received from the instance). This function uses conditional expressions to call the right constructor function to initialize your values, let's say you have different sets of possible initial values.

If you need to specify other arguments (for example, which may only be relevant at run time), you can use the default values ​​in init () to allow additional arguments, and initialize them in init , as usual.

 class MyClass: def __init__(self,argsSet1, otherAttribute="Assigning this default value to make this other argument optional",): self.selectArgSet(argsSet1) self.otherAttribute = otherAttribute print otherAttribute def selectArgSet(self,ArgSet1): if ArgSet1 == "constructorArgSet1": self.constructorArgSet1() elif ArgSet1 == "constructorArgSet2": self.constructorArgSet2() def constructorArgSet1(self): print "Use this method as Constructor 1" self.variable1 = "Variable1 value in Constructor 1" self.variable2 = "Variable2 value in Constructor 1" print self.variable1 print self.variable2 def constructorArgSet2(self): print "Use this method as Constructor 2" self.variable1 = "Variable1 value in Constructor 2" self.variable2 = "Variable2 value in Constructor 2" print self.variable1 print self.variable2 myConstructor_1_Instance = MyClass("constructorArgSet1") myConstructor_2_Instance = MyClass("constructorArgSet2", "You can still initialize values normally") 

The output of which:

Use this method as a constructor 1

Variable1 value in constructor 1

Variable2 value in constructor 1

Assign a default value to make this other argument optional

Use this method as constructor 2

Variable1 value in constructor 2

Variable2 value in constructor 2

You can still initialize the values

0
Mar 15 '15 at 5:09
source share



All Articles