2013-10-10 13 views
11

我有一個類AbstractDataHandle,他的init方法和一個類Classifier。我想在Classifier,Java中有兩個構造函數。一個從它的超級繼承而來,一個是全新的。Python中的多個構造函數,使用繼承

這會是這樣的(但我打算「保持」兩個構造函數):

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) 

我可以在一個班兩個構造函數? 如果是的話,我可以有一個從超類繼承的構造函數,並添加一個新的?

預先感謝您。

+2

你可以有子類構造函數調用超構造函數通過'超'http://stackoverflow.com/questions/576169/understanding-python-super-and-init-methods –

+0

謝謝你的答案。事情是,調用超級,我只有一個構造函數。 如果參數的數量(和/或類型)不同,則Java中可能有多個參數。我想知道python中是否存在相同的東西。 –

+1

您可以使用'@ classmethod'來創建任意數量的構造函數。 – roippi

回答

38

在一個類中不能有兩個構造函數。

構造函數必須命名爲__init__。而且,與Java不同,Python不允許通過它們的參數類型來重載函數或方法。所以,如果你有兩個構造函數,它們都是相同的函數。

有幾種解決方法。


使用@classmethod S作爲替代構造:

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,其可與now構成,fromtimestamp,或一些其他的替代構造,除了default


使用默認值,關鍵詞只,和/或可變參數的參數,使一個構造函數,可以調用不同的方式:

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

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 

在任何情況下,你可以分解出共性成一個單一的「基地」初始化。例如:

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) 

當然在任何情況下,纔有可能吃早餐無垃圾郵件。

+3

只是爲了記錄,'__init__'不是構造函數,它(正如名字所暗示的)是一個初始化器。正確的構造函數是'___新_' –

+4

@brunodesthuilliers:文檔重複調用'__init__'構造函數(例如,[here](http://docs.python.org/3.3/reference/datamodel.html#object.__init__)) 。這與其他語言一致 - 例如,在C++中,與使用初始化值的類名稱相同的方法是構造函數;分配存儲的方法叫做new,是分配器。 – abarnert

+2

@brunodesthuilliers:當文檔仔細地講話時,「構造函數」只引用類對象的_call_,這可能最終調用'__new__'和/或'__init__',而不是調用任何一種方法。但是當他們不小心說話時,它總是'__init__',而不是'__new__',這就是所謂的構造函數。 – abarnert

3

您可以使用作爲工廠方法工作的類方法。這是多重構造函數的最佳方法。第一個參數'cls'是類本身,而不是實例,因此類方法中的cls('Truck')調用類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') 

然後調用工廠方法是這樣的:

mycar = Car.Sport() 
0

有在接受答案的方法,但我認爲這是一個相當靈活的。它很複雜,但非常靈活。

當這個類被調用時,init調用一個方法並傳遞一個字符串參數(從實例化獲得)。該函數使用條件來調用正確的「構造函數」函數來初始化您的值,假設您有不同的可能起始值集合。

如果您需要提供其他參數(例如,可能只有在運行時的值),你可以使用默認值在初始化()允許可選參數,並像往常一樣初始化那些初始化

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") 

其中的輸出是:

使用此方法作爲構造1個

在構造

變量1的值1

在構造1

變量2值

分配默認值使其他參數可選

使用此方法,構造函數2

在構造

變量1值2

在構造函數變量2值2個

,您仍然可以初始化值正常