1、__ new__, __ init__, __ call__
__ new__(cls, *args, **kwargs) 建立物件時呼叫,返回當前物件的一個例項;注意:這裡的第一個引數是cls即class本身
__ init__(self, *args, **kwargs) 建立完物件後呼叫,對當前物件的例項的一些初始化,無返回值,即在呼叫__new__之後,根據返回的例項初始化;注意,這裡的第一個引數是self即物件本身
__ call__(self, *args, **kwargs) 如果類實現了這個方法,相當於把這個型別的物件當作函式來使用,相當於 過載了括號運算子
繼承自object的新式類才有__ new__
__ new__至少要有一個引數cls,代表要例項化的類,此引數在例項化時由Python直譯器自動提供
__ new__必須要有返回值,返回例項化出來的例項,這點在自己實現_ new__時要特別注意,可以return父類__ new__出來的例項,或者直接是object的 _new__出來的例項
__ init__有一個引數self,就是這個 __ new__返回的例項,__ init__在__ new__的基礎上可以完成一些其它初始化的動作,__ init__不需要返回值
若_ _new__沒有正確返回當前類cls的例項,那__ init__是不會被呼叫的,即使是父類的例項也不行
http://www.cnblogs.com/ifantastic/p/3175735.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
class Foo(object): def __init__(self, *args, **kwargs): ... def __new__(cls, *args, **kwargs): return object.__new__(cls, *args, **kwargs) # 以上return等同於 # return object.__new__(Foo, *args, **kwargs) # return Stranger.__new__(cls, *args, **kwargs) # return Child.__new__(cls, *args, **kwargs) class Child(Foo): def __new__(cls, *args, **kwargs): return object.__new__(cls, *args, **kwargs) # 如果Child中沒有定義__new__()方法,那麼會自動呼叫其父類的__new__()方法來製造例項,即 Foo.__new__(cls, *args, **kwargs)。 # 在任何新式類的__new__()方法,不能呼叫自身的__new__()來製造例項,因為這會造成死迴圈。因此必須避免類似以下的寫法: # 在Foo中避免:return Foo.__new__(cls, *args, **kwargs)或return cls.__new__(cls, *args, **kwargs)。Child同理。 # 使用object或者沒有血緣關係的新式類的__new__()是安全的,但是如果是在有繼承關係的兩個類之間,應避免互調造成死迴圈,例如:(Foo)return Child.__new__(cls), (Child)return Foo.__new__(cls)。 class Stranger(object): ... # 在製造Stranger例項時,會自動呼叫 object.__new__(cls) |
1 2 |
也可以這麼呼叫 new_class = super(RenameMethodsBase, cls).__new__(cls, name, bases, attrs) |
通常來說,新式類開始例項化時,new()方法會返回cls(cls指代當前類)的例項,然後該類的init()方法作為構造方法會接收這個例項(即self)作為自己的第一個引數,然後依次傳入new()方法中接收的位置引數和命名引數。
注意:如果new()沒有返回cls(即當前類)的例項,那麼當前類的init()方法是不會被呼叫的。如果new()返回其他類(新式類或經典類均可)的例項,那麼只會呼叫被返回的那個類的構造方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class Foo(object): def __init__(self, *args, **kwargs): ... def __new__(cls, *args, **kwargs): return object.__new__(Stranger, *args, **kwargs) class Stranger(object): ... foo = Foo() print type(foo) # 列印的結果顯示foo其實是Stranger類的例項。 # 因此可以這麼描述__new__()和__ini__()的區別,在新式類中__new__()才是真正的例項化方法,為類提供外殼製造出例項框架,然後呼叫該框架內的構造方法__init__()使其豐滿。 # 如果以建房子做比喻,__new__()方法負責開發地皮,打下地基,並將原料存放在工地。而__init__()方法負責從工地取材料建造出地皮開發招標書中規定的大樓,__init__()負責大樓的細節設計,建造,裝修使其可交付給客戶。 |
2、__ del__
它不實現語句 del x (以上程式碼將不會翻譯為 x.__ del__() )。它定義的是當一個物件進行垃圾回收時候的行為。當一個物件在刪除的時需要更多的清潔工作的時候此方法會很有用,比如套接字物件或者是檔案物件。注意,如果直譯器退出的時候物件還存存在,就不能保證 __ del__ 能夠被執行
1 2 3 4 5 6 7 8 9 10 11 12 |
from os.path import join class FileObject: '''給檔案物件進行包裝從而確認在刪除時檔案流關閉''' def __init__(self, filepath='~', filename='sample.txt'): #讀寫模式開啟一個檔案 self.file = open(join(filepath, filename), 'r+') def __del__(self): self.file.close() del self.file |
3、用於比較的魔術方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
Python對實現物件的比較,使用魔術方法進行了大的逆轉,使他們非常直觀而不是笨拙的方法呼叫。 而且還提供了一種方法可以重寫Python對物件比較的預設行為(通過引用)。以下是這些方法和他們的作用。 __cmp__(self, other) __cmp__ 是最基本的用於比較的魔術方法。它實際上實現了所有的比較符號(<,==,!=,etc.),但是它的表現並不會總是如你所願(比如,當一個例項與另一個例項相等是通過一個規則來判斷,而一個例項大於另外一個例項是通過另外一個規則來判斷)。 如果 self < other 的話 __cmp__ 應該返回一個負數,當 self == other 的時候會返回0 ,而當 self > other 的時候會返回正數。通常最好的一種方式是去分別定義每一個比較符號而不是一次性將他們都定義。 但是 __cmp__ 方法是你想要實現所有的比較符號而一個保持清楚明白的一個好的方法。 __eq__(self, other) 定義了等號的行為, == 。 __ne__(self, other) 定義了不等號的行為, != 。 __lt__(self, other) 定義了小於號的行為, < 。 __gt__(self, other) 定義了大於等於號的行為, >= 。 class Word(str): '''儲存單詞的類,定義比較單詞的幾種方法''' def __new__(cls, word): # 注意我們必須要用到__new__方法,因為str是不可變型別 # 所以我們必須在建立的時候將它初始化 if ' ' in word: print "Value contains spaces. Truncating to first space." word = word[:word.index(' ')] #單詞是第一個空格之前的所有字元 return str.__new__(cls, word) def __gt__(self, other): return len(self) > len(other) def __lt__(self, other): return len(self) < len(other) def __ge__(self, other): return len(self) >= len(other) def __le__(self, other): return len(self) <= len(other) |
http://pycoders-weekly-chinese.readthedocs.org/en/latest/issue6/a-guid…