2016-03-10 100 views
0

說我有兩個容器類的行爲稍有不同,但有很多常用的方法。我使用mixin類將這些方法添加到兩個容器中。在python中,如何從mixin類的方法調用正確的構造函數?

例如:

class SpamContainer(Mixin, BaseClass): 
    def __init__(self, spam): 
     super(SpamContainer, self).__init__(spam) 

class DifferentSpamContainer(Mixin, DifferentBaseClass): 
    def __init__(self, spam): 
     super(DifferentSpamContainer, self).__init__(spam) 

class Mixin(object): 
    # has no __init__() 

    def useful_method(self): 
     for s in self.spam: 
      # do something 

現在我想一個新的方法添加到Mixin,創建並返回一個新的容器對象 - 如果selfSpamContainer,我要創建其中的一個,而如果它是一個DifferentSpamContainer,我想創建其中的一個。我如何從Mixin的方法中調用正確的構造函數?

我想也許我可以用這樣的:

class Mixin(object): 
    def method(self, spam): 
     return self.__init__(spam) 

class Mixin(object): 
    def another_method(self, spam): 
     return self.__class__(spam) 

,但我無法得到它的工作。

我正在使用python 2.7。

+0

要非常小心地使用Mixins來做任何不重要的事情,它們可以很快失去控制。你爲什麼要將構造功能放到mixin的實例級別(例如,相對於在基類中調用init方法(或類級構造函數)?) –

+0

我不認爲我理解爲什麼不能你只是使用子類的構造函數? –

回答

3

您使用classmethod

class Mixin(object): 
    @classmethod 
    def alternate_constructor(cls, spam): 
     return cls(spam) 

請注意,您的混入的使用在這裏似乎是有點過。通常,在使用繼承(單個或多個)時,您需要調用基類中的方法。例如在你的情況下,Mixin和它混合的各個類不能同時調用它們的構造函數。實際上,例如,您甚至不會在BaseClass中調用__init__,例如SpamContainer。這有點奇怪。如果您打算使用多重繼承進行任何工作,我強烈建議您閱讀Super Considered Super!和配套文章Super considered harmful。這將幫助您瞭解多繼承的缺陷(以及如何避免它們)。

+0

你忘記聲明'cls'參數 – jwodder

+0

@jwodder - 謝謝,我已經開始着手「如果你要和Mixins一起工作,你應該小心」 – mgilson

+0

謝謝,我已經編輯了我的問題以包含對基類的「super()」調用。在除了答案之前,我會讀一下關於「@ classmethod」和你的其他鏈接。 –

相關問題