2014-01-31 67 views
0

我有以下程序:什麼是實例基於一類程序的Python的方式

class MyClass(object): 
    def __init__(self): 
     pass 
    def hello(self): 
     print ("hello") 

if __name__ == "__main__": 
    a = MyClass() 
    a.hello() 

它也可以推出,

class MyClass(object): 
    def __init__(self): 
     self.hello() 
    def hello(self): 
     print ("hello") 

if __name__ == "__main__": 
    MyClass() 

是否有一個理由,更喜歡一種風格另一方面,蟒蛇明智(個人喜好之外)?換句話說:在__init__內處理程序一般流程和邏輯與在班級之外流動相比,是否存在優勢/劣勢?

該代碼旨在作爲獨立腳本運行,與上述示例非常相似,只是更復雜。

+2

爲什麼要用這個類呢? – user2357112

+1

後者在語義上是錯誤的,因爲構造函數不應該做任何額外的工作,以及初始化對象。如果你真的想避免一個額外的行,你可以使用'MyClass()。hello()'。 –

+0

@ user2357112:爲什麼不呢?該程序顯然更復雜,在函數之間引用'self'變量(除其他之外) – WoJ

回答

1

我發明了另一個例子,它顯示了在第二種風格中所有課程的動機。顯然,這是大量過度設計的。讓我們假設除了你的調用之外,還有一些其他的代碼會使用這個類去做一些其他的事情,而不是隻調用一個函數,所以這個複雜的接口是合理的。

class MyClass(object): 
    def __init__(self): 
     self.get_config() 
     self.validate_config() 
     self.hello() 
    def get_config(self): 
     self.message = "hello" 
    def validate_config(self): 
     # I'm not claiming this is good practice, just 
     # an example of multiple methods that share state 
     if not self.message: 
      raise Exception() 
    def hello(self): 
     print(self.message) 

if __name__ == "__main__": 
    MyClass() 

那麼我們在這裏有什麼?基本上,您正在使用MyClass的調用,而不是爲了創建一個對象(儘管它確實會這樣做並且放棄它),但是卻是爲了執行該對象的方法__init__。它當然有效,但它不是「自然的」。自然的事情是,如果你想運行「一些東西」,你可以調用一個包含這些東西的函數。你並不特別希望它返回一些你根本不關心的對象。如果東西需要保持一定的狀態,做它的工作,然後就可以處理,你不需要它告訴你在最後的狀態:

class MyClass(object): 
    def __init__(self): 
     self.get_config() 
     self.validate_config() 
    def get_config(self): 
     self.message = "hello" 
    def validate_config(self): 
     # I'm not claiming this is good practice, just 
     # an example of multiple methods that share state 
     if not self.message: 
      raise Exception() 
    def hello(self): 
     print(self.message) 

def main(): 
    MyClass().hello() 

if __name__ == "__main__": 
    main() 

這看起來更像是你的第一個樣式比你第二,所以在這個意義上我更喜歡第一個。

具有main函數可能會使它在一些類型的線束(如Python提示符或測試工具)下使用模塊更容易一點。不過這並不是必要的。如果有人想要像__name__ == '__main__'那樣做,那麼最壞的情況下他們可以複製該來源。

0

我很欣賞你的例子只是說明你的觀點,並沒有因爲要打印「你好」,需要一個類來做到這一點;)

if __name__ == "__main__":在文件中表明,該文件也適用進口。您是否希望課程在實例化時始終打印「hello」?通常,行爲在方法中,並且__init__僅包含初始化。

+0

是的,這是解釋我的問題的最小代碼:)我總是在我的代碼中放置'if __name__ =='__main __「:'條件,主要是爲了直觀地分離實際的程序 - 即使稍後沒有計劃導入。 – WoJ

+0

@WoJ正確的,所以初始化類的東西 - 包括你想要在整潔的方法中放入的代碼 - 進入構造函數,其行爲出現在其他人調用的方法中。 – Will

1

你總是可以問自己:如果我實例化這個類的100個實例,這仍然是我想要的行爲嗎?

將這個對象應該做的所有事情加載到一個單獨的方法中,例如init(self),這使得主要方法儘可能短,這是很有誘惑力的。只要這保留你的私人腳本,就沒有必要選擇一個。

但是,一旦代碼被共享,或者該類由另一個腳本導入,則通過使初始化()僅執行一些必要的初始化命令來提高可重用性。

0

那麼,你在這裏解決不同的事情。通常,創建對象的目的不是讓它觸發某些東西然後消失(這更像是一個函數的工作)。相反,你通常想反對留下來,並與之互動。這樣,你就一定要保存在變量對象引用:

obj = MyClass() 

接下來,你應該想想,如果事情應該始終被每當創建對象稱爲。如果是這樣的話,那麼是的,你可能應該把它放到__init__。如果即使只是一個較小的情況,它也不是真的,那麼你應該分開它,以便可以分別進行初始化和動作。

你的例子顯然非常簡單,所以它首先沒有多少意義。但通常,我會將hello視爲一個公共API,我有可能在擁有該類型的對象時調用它。另一方面,我不希望只在創建對象時自動調用它。

可能有些情況下,像這樣的東西是有用的和想要的,但一般來說,你更喜歡明確地調用方法。

相關問題