Multiple constructors in python, using inheritance

前端 未结 3 1778
走了就别回头了
走了就别回头了 2020-12-15 09:09

I have a class AbstractDataHandle, whith his init method, and a class Classifier. I would like to have two constructors in Classifier, Java like. One inheri

相关标签:
3条回答
  • 2020-12-15 09:48

    You can use class methods, which work as factory methods. That's imho the best approach for multiple constructors. First argument 'cls' is class itself, not it's instance, so cls('Truck') in class method invokes constructor for class Car.

    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 factory method this way:

    mycar = Car.Sport()
    
    0 讨论(0)
  • 2020-12-15 09:48

    There are the methods in the accepted answer, but I think this one is fairly flexible. It's convoluted, but very flexible.

    When the class is instiated, init calls a method and pass it a string argument (obtained from instantiation). That function uses conditionals to call the right "constructor" function to initialize your values, let's say you have different sets of possible starting values.

    If you need to provide other arguments (e.g. that might have a value only at runtime), you can use default values in init() to allow optional arguments, and initialize those in init as you normally would.

    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 is:

    Use this method as Constructor 1

    Variable1 value in Constructor 1

    Variable2 value in Constructor 1

    Assign 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 values normally

    0 讨论(0)
  • 2020-12-15 09:57

    You can't have two constructors in one class.

    Constructors have to be named __init__. And, unlike Java, Python doesn't 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 a few ways around this.


    Use @classmethods as alternate 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 constructed with now, fromtimestamp, or a few other alternate constructors, besides the default.


    Use default-valued, keyword-only, and/or variable-argument parameters to make a single constructor that can be called 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 that each have 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 any of these cases, you can factor out commonalities into a single "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 is it possible to have breakfast without spam.

    0 讨论(0)
提交回复
热议问题