2012-03-16 67 views
4

我一直在努力奮鬥三天,圍繞__init__和「自我」,從Python Python入門練習42開始,繼續閱讀部分Python文檔,Alan Gauld's chapter on Object-Oriented Programming,Stack threads like this one on "self",and this one和坦率地說,我準備用磚頭打我自己,直到我昏過去。這就是說,我已經注意到一個非常常見的約定,在最初的__init__定義中,隨後是(self,foo),然後立即在該定義中聲明self.foo = foo。Python:必須__init __(self,foo)總是跟着self.foo = foo?

從LPTHW,ex42:

class Game(object): 
    def __init__(self, start): 
     self.quips = ["a list", "of phrases", "here"] 
     self.start = start 

從阿蘭·高爾德:

def __init__(self,val): self.val = val 

我在那可怕的空間,讓我可以看到,這裏有一個大的事情我沒有變,而且無論我讀了多少關於它並試圖找出它,它都是不透明的。也許如果有人能夠向我解釋這一點點的一致性,那麼燈就會亮起來。這是因爲我們需要說變量的「foo」將始終等於(foo)參數,它本身包含在自動分配給它所連接的def的「self」參數中?

回答

6

你可能想研究面向對象編程

寬泛地說,當你說

class Game(object): 
    def __init__(self, start): 
     self.start = start 

你說:

  • 我有一個類型的名爲 「東西」Game

  • 每當新的Game被創建,它會要求我一些額外的信息,start。 (這是因爲Game的初始化,命名爲__init__,詢問此信息。)

  • 初始化程序(也被稱爲‘構造’,雖然這是一個輕微用詞不當)需要知道哪個對象(剛剛創建)它正在初始化。這是第一個參數 - 通常按照慣例稱爲self(但您可以調用其他任何東西...)。

  • 遊戲可能需要記住我給它的start是什麼。因此,存儲這些信息的「內部」本身,通過創建變量實例也命名start(沒有什麼特別的,只是任何你想要的名稱),並分配start參數爲start變量的值。

    • 如果它沒有存儲參數的值,它將不具有該信息供以後使用。

希望這解釋了發生了什麼事。

+0

很好的解釋 – Wei 2012-03-16 00:57:16

+0

重要的是,你可以指定參數給任何屬性,比如'self.abc'。以同樣的方式命名屬性只是你如何構造代碼的問題。 – 2012-03-16 00:59:27

+0

@FelixKling:我做了一個小小的修改,使其更加清晰,謝謝。 – Mehrdad 2012-03-16 01:00:47

0

參數名稱應該是有意義的,以表達它們在函數/方法中扮演的角色或關於其內容的一些信息。

您可以看到構造函數的參數更加重要,因爲它們通常是新實例工作所必需的,並且包含了該類的其他方法所需的信息。

想象一下,你有一個Game類,它接受playerList

class Game: 

    def __init__(self, playerList): 
     self.playerList = playerList # or self.players = playerList 

    def printPlayerList(self): 
     print self.playerList   # or print self.players 

該列表在該類的各種方法中都需要。因此將其分配給self.playerList是有意義的。你也可以把它分配到self.players,不管你覺得什麼更舒服,認爲是可以理解的。但是,如果您不將其分配給self.<somename>,則無法通過其他方法訪問它。

因此,如何命名參數/屬性/等(there are some special class methods though)沒有什麼特別之處,但使用有意義的名稱會使代碼更易於理解。或者如果您有以下情況,您是否會理解上述課程的含義:

class G: 

    def __init__(self, x): 
     self.y = x 

    def ppl(self): 
     print self.y 

? :)它確實一樣,但很難理解...

2

我不太清楚你錯過了什麼,所以讓我打一些基本項目。

有在Python class對象,一個是比較少見的用戶不用擔心,叫__new__,另一個是更常用的兩個「特殊」 intialization的名字,叫__init__

當您調用類對象構造函數時,例如(根據你的例子)x = Game(args),這首先調用Game.__new__來獲取內存中的哪個對象,然後用Game.__init__來填充那個內存。大多數時候,你可以允許底層的內存分配,你只需要填寫內存。(你可以使用自己的分配器來處理特殊的奇怪的罕見情況,比如永遠不會改變的對象,可以共享身份,普通的方式整數都是這樣的,它也適用於那些奇怪的東西的「元類」,但這些都是後來的主題。)

您的Game.__init__函數被調用時,「所有參數都放在構造函數中」加上一個放在前面,這是爲該對象本身分配的內存。 (對於「普通」對象,主要是一個「屬性」字典,加上類魔法膠水,但對於__slots__屬性字典省略的對象)。命名第一個參數self只是一個約定 - 但不違反它,如果你這樣做,人們會恨你。 :-)

沒有什麼要求您將所有參數保存到構造函數中。您可以設置任何或所有實例的屬性你喜歡:

class Weird(object): 
    def __init__(self, required_arg1, required_arg2, optional_arg3 = 'spam'): 
     self.irrelevant = False 
    def __str__(self): 
     ... 

的事情是,一個奇怪的()實例初始化後沒什麼用,因爲你需要通過被簡單地扔掉兩個參數,並給予第三個可選的參數,它也扔掉:

x = Weird(42, 0.0, 'maybe') 

在需要那些濺離參數的唯一一點是爲將來的擴展,因爲它是(你可能有早期發育過程中,這些未使用的字段)。所以如果你沒有立即使用和/或將參數保存到__init__,那麼Weird肯定有些奇怪。

順便說一句,在類定義中使用(object)的唯一原因是向Python 2.x指出這是一個「新風格」類(區別於非常古老的Python「僅實例」類)。但通常最好使用它 - 它使我上面所說的關於object.__new__是真實的,例如:-) - 直到Python 3,舊式的東西完全消失。

相關問題