2013-10-10 63 views
0

我正在使用@classmethod編寫一個具有多個構造函數的類。現在,我希望__init__構造函數以及類方法構造函數在執行其他任務之前調用該類的一些例程以設置初始值。python中的多元構造函數調用相同的例程

__init__這通常是用自做:

def __init__(self, name="", revision=None): 
    self._init_attributes() 

def _init_attributes(self): 
    self.test = "hello" 

從類方法構造,我會調用另一個類方法來代替,因爲不創建實例(即self),直到我離開類方法與return cls(...)。現在,我可以打電話給我_init_attributes()方法

@classmethod 
def from_file(cls, filename=None) 
    cls._init_attributes() 
    # do other stuff like reading from file 
    return cls() 

,這實際工作(在我沒有得到一個錯誤的感覺,我的確可以看到執行c = Class.from_file()後的測試屬性。但是,如果我沒有理解的東西如果我使用可變對象(例如列表)初始化屬性,那麼此類的所有實例將使用相同的列表,而不是這是正確的嗎?如果是這樣,是否有方法來初始化classmethods中的「實例」屬性,還是必須以這樣的方式編寫代碼:所有的屬性初始化都在init

嗯。實際上,在寫這篇文章的時候:我甚至可能比我想象的更麻煩,因爲init將會從classmethod返回時調用,不是嗎?那麼處理這種情況的適當方法是什麼?

注:文章[1]討論了一個有點類似的問題。

+0

相反,你不能只是'_init_attributes()'@ staticmethod'並顯式傳遞它的屬性需要初始化的對象嗎? – martineau

回答

1

是的,你正確理解事情:cls._init_attributes()將設置類屬性,而不是實例屬性。

同時,由構造函數構造並返回一個實例。在構建它並返回它之間時,您可以撥打_init_attributes()。換句話說:

@classmethod 
def from_file(cls, filename=None) 
    obj = cls() 
    obj._init_attributes() 
    # do other stuff like reading from file 
    return obj 

但是,你說得對,構建並返回一個實例的唯一明顯的方法是隻是調用cls(),它將調用__init__


但這是容易解決:只要有備用的構造函數傳遞一些額外參數__init__意思是「跳過常規的初始化,我打算以後做」。例如:

def __init__(self, name="", revision=None, _skip_default_init=False): 
    # blah blah 

@classmethod 
def from_file(cls, filename=""): 
    # blah blah setup 
    obj = cls(_skip_default_init=True) 
    # extra initialization work 
    return obj 

如果你想使這個不太明顯,可以經常服用**kwargs,並檢查它的方法體內......但請記住,這是Python的;你不能阻止人們做愚蠢的事情,你所能做的就是明確表示他們是愚蠢的。而且_skip_default_init應該足夠處理這個問題。


如果您確實想要,也可以覆蓋__new__。構造對象不會調用__init__,除非__new__返回cls或其某個子類的實例。所以,你可以給__new__一個標誌,告訴它跳過__init__,通過自動更新obj.__class__,然後自己恢復__class__。這真的很不方便,但可以想象會有用。


一個更清潔的解決方案,但由於某些原因,甚至不常見的Python的是從Smalltalk中借用「類簇」的想法/ ObjC:創建具有不同__init__一點不super私有子(或者故意跳過它的直接基地和super),然後讓你的基類中的替代構造函數只返回該子類的一個實例。


另外,如果你不想叫__init__的唯一原因是這樣你就可以做同樣的事情__init__會做......爲什麼? DRY代表「不要重複自己」,而不是「向後彎腰,想方設法強迫自己重複自己」,對吧?

+0

非常感謝這非常明確和有用的答案!正是我所希望的。 – maschu