這裏有幾點你需要知道Python如何做面向對象,如果你來自Java/PHP。
在Python中,類也是非常普通的對象。這意味着類自己可以有成員變量(我們通常只是稱它們爲屬性)。您在類塊中分配的所有名稱都將成爲類本身的屬性,而不是其任何實例的屬性(包括創建方法的函數def
塊;這就是Python中的所有方法)。
由於您通常有一個類和許多實例,類屬性可以爲Java類中的靜態變量提供類似的用途,但它們並不完全相同。
在類塊中分配名稱從不在類的實際屬性上創建屬性; 只有在對象(任何對象,類或普通實例)上創建屬性的方法是在其存在時分配它們。因此,Python的__init__
方法中必須存在類的實例所有變量的標準聲明,並在self
上指定屬性。
例如:
class Foo(object):
foo = "I am a class attribute"
def __init__(self):
self.bar = "I am an instance attribute"
如果這往往混淆了新的Python程序員是試圖讀從一個實例將實際工作,並找到類屬性(這是方法調用如何找到foo
屬性他們應該調用的函數)。所以它看起來像在類塊中聲明實例屬性,可以用於第一次休閒遊戲。但實際上只有一個屬性foo
,在所有實例之間共享,如果它是可變對象並且您希望每個實例都有其自己的副本,則這可能非常糟糕。
在Python中沒有訪問控制,所以沒有私有變量這樣的事情。這是因爲Python具有足夠的動態性,以至於你總能繞過任何這樣的限制,使它們變得毫無意義。
相反,Python程序員傾向於依靠文檔和約定來確保編寫客戶端代碼的程序員知道哪些名稱是公共API的一部分,哪些是實現細節。然後,我們相信每個人都會主要遵守規則,那些不需要處理他們的代碼的人就是他們不應該依賴於變化的東西。
無論如何,在任何語言中,具有微不足道的getter和setter的屬性都是「公共」的;唯一可能的擔憂是你可能「有一天」想要改變getter/setter的實現,以便在不改變你的接口的情況下它們不再微不足道。 Python可以通過屬性來解決這個問題(基本上允許你進行方法調用,看起來像讀或寫屬性),所以絕對沒有理由擁有getter/setter方法,除非實際上有更多的事情發生。
因此,一般來說,如果期望客戶端代碼操縱對象的接口包括讀取和寫入字段,則只需記錄一個普通屬性可供讀取和寫入。如果你想清楚一個屬性(或方法)純粹是爲了內部使用,通常的慣例是用一個下劃線開始名稱。這會強制任何使用該名稱的人知道他們正在訪問內部名稱(因爲他們必須鍵入前導下劃線),所以您不必擔心有人會「意外」使用私有屬性。
關於構造,只是對待__init__
方法__construct
從PHP,它會做你所期望的(但一定要記住,Python方法明確收到self
參數;沒有隱含this
)。
有這個神話,__init__
與構造函數有點不同,所以你不應該稱它爲一個。至於我可以告訴罪魁禍首是Dive Into Python,這相當奇怪的說:
這將是誘人的,但不正確調用這個 類的構造函數。這很誘人,因爲它看起來像一個構造函數(按照約定 約定,__init__
是爲該類定義的第一個方法),行爲 就像一個(它是在該類的新創建的 實例中執行的第一段代碼),甚至聽起來像一個(「初始化」當然 建議一個構造函數性質)。不正確,因爲對象具有 的時間已被調用__init__
被調用,並且您的 已具有對該類的新實例的有效引用。
但「對象已經由時間__init__
構造被調用,並且你已經有了類的新實例的有效引用」精確表徵的構造是如何傳統的工作,所以我不知道什麼時候作者正試圖在那裏。
(該出現採取官方行是MyClass(arg1, arg2)
是構造表達; __init__
和__new__
都描述爲接收被賦予給構造表達式的所有參數,並且__init__
明確地稱爲構造這兩個術語都很少使用的文檔;他們只是說__init__
最重要的時間)
所以我勸你忽略人誰試圖告訴你,__init__
不是構造函數。你將通過類比構造函數來理解__init__
,而不是試圖理解他們在構造函數和__init__
之間做出的關鍵區別。
把所有在一起,你的PHP類的成語翻譯將是簡單如下:
class MyClass(object):
def __init__(self, myMember):
self.myMember = myMember
好吧,'__init__'是一個構造函數,就像PHP的'__construct'是一個構造函數一樣。無論您是否同意這個術語,'__new__'是其他語言稱爲工廠的東西(有些語言支持可以方便地調用它),並且它比其他語言稱爲構造函數的功能嚴格得多(可以返回不同或已有的對象) 。所以,OP:只需使用'__init__',句號。 – delnan
在我有經驗的每種* OO語言中,您編寫的用於初始化對象並稱爲構造函數的代碼塊將在已存在的對象上調用。因此,如果Python和PHP構造函數「不是真正的構造函數」,那麼Java或C++構造函數都不是。 – Ben
爲什麼你要將'__new__'作爲靜態方法?我傾向於認爲它是一個類方法,因爲第一個參數是一個類... – mgilson