关于oop:python中的多个构造函数,使用继承

Multiple constructors in python, using inheritance

我有一个类abstractdatahandle(它的init方法)和一个类分类器。我希望在分类器中有两个构造函数,比如Java。一个继承了它的超类,一个全新的。

它类似于(但我打算"保留"这两个构造函数):

1
2
3
4
5
6
7
8
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)

一个类中可以有两个构造函数吗?如果是,我可以从一个超类继承一个构造函数,并添加一个新的吗?

提前谢谢。


一个类中不能有两个构造函数。

必须将构造函数命名为__init__。而且,不像Java,Python不允许根据它们的参数类型重载函数或方法。所以,如果您有两个构造函数,它们都是相同的函数。

有几种方法可以解决这个问题。

使用@classmethods作为备选施工人员:

1
2
3
4
5
6
7
8
9
10
11
12
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

标准库中的一个简单示例是datetime.datetime,它可以使用nowfromtimestamp或其他一些可选的构造函数(除了默认值)来构造。

使用默认值、仅关键字和/或变量参数来生成可通过不同方式调用的单个构造函数:

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

int就是这样一个例子:您可以从一个字符串和一个基创建它,或者从一个知道如何将自己转换为整数的参数创建它。

创建每个子类都有不同的构造函数:

1
2
3
4
5
6
7
8
9
10
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

在任何这些情况下,您都可以将共性分解为单个"基"初始值设定项。例如:

1
2
3
4
5
6
7
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)

当然,在任何情况下,早餐都不可能没有垃圾邮件。


您可以使用类方法,它作为工厂方法工作。对于多个构造函数来说,这是最好的方法。第一个参数"cls"是类本身,而不是实例,因此类方法中的cls("truck")调用类car的构造函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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')

然后用这种方式调用工厂方法:

1
mycar = Car.Sport()


在公认的答案中有一些方法,但我认为这个方法相当灵活。这很复杂,但很灵活。

当类被插入时,init调用一个方法并传递一个字符串参数(从实例化中获得)。该函数使用条件调用正确的"构造函数"函数来初始化您的值,假设您有不同的可能起始值集。

如果需要提供其他参数(例如,可能只有在运行时才有值),可以使用init()中的默认值来允许可选参数,并像通常那样初始化init中的参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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"
)

其输出为:

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