python中的多个构造函数,使用继承

Luc*_*iro 11 python oop inheritance constructor python-2.7

我有一个AbstractDataHandle类,它的init方法和类Classifier.我想在Classifier中有两个构造函数,Java就像.一个继承自它的超类,一个全新的.

它会像(但我打算"保留"两个构造函数):

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)
Run Code Online (Sandbox Code Playgroud)

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

先感谢您.

aba*_*ert 43

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

必须命名构造函数__init__.而且,与Java不同,Python不允许按参数类型重载函数或方法.所以,如果你有两个构造函数,它们都是相同的函数.

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


使用@classmethods作为替代构造函数:

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
Run Code Online (Sandbox Code Playgroud)

从标准库一个简单的例子是datetime.datetime,可以用被构造now,fromtimestamp或一些其他的替代构造,除了默认.


使用default-valued,keyword-only和/或variable-argument参数来创建可以以不同方式调用的单个构造函数:

class Breakfast(object):
    def __init__(self, eggs=0, spam=5):
        self.spam, self.eggs = spam, eggs
Run Code Online (Sandbox Code Playgroud)

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


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

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
Run Code Online (Sandbox Code Playgroud)

在任何这些情况下,您都可以将共性分解为单个"基础"初始化程序.例如:

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)
Run Code Online (Sandbox Code Playgroud)

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

  • @brunodesthuilliers:你可以说这些文档措辞严厉.但是说"`__init__`不是构造函数......正确的构造函数是`__new__` ..."是错误的.文档调用`__init__`而不是`__new__`构造函数,而`__init__`是与其他语言中的构造函数相同的函数; 你不能只是将术语重新定义为与其他人意味着不同的东西,然后说"根据我的特殊定义,你是不正确的." (7认同)
  • @brunodesthuilliers:文档反复调用构造函数`__init__`(例如,[here](http://docs.python.org/3.3/reference/datamodel.html#object.__init__)).这与其他语言一致 - 例如,在C++中,与获取初始化值的类同名的方法是构造函数; 分配存储的方法称为"new"是分配器. (4认同)
  • 只是为了记录,`__ init__`是*不是构造函数,它是(顾名思义)一个初始化程序.正确的构造函数是`_new__` (3认同)
  • @brunodesthuilliers:当文档仔细说话时,"构造函数"只引用_call_到类对象,它可能最终调用`__new__`和/或`__init__`,而不是任何一种方法.但是当他们不小心说话时,它总是`__init__`,而不是`__new__`,这被称为构造函数. (2认同)