Python——特殊方法

來源:互聯網
上載者:User

標籤:

  Python中以雙底線開頭和結尾的函數稱為特殊函數,對於執行個體執行一些特定的運算時,Python會自動視圖調用這些執行個體的特殊方法,從而在Python中可以很輕易地實現運算子的重載。

  Python中有一些通用的特殊函數:

 

1. 初始化與終止化

 __new__(cls[, args...]) 

  __new__()是一個靜態方法,用於根據類型建立執行個體。Python在調用__new__()方法獲得執行個體後,會調用這個執行個體的__init__()方法,然後將最初傳給__new__()方法的參數都傳給__init__()方法。

 

 __init__() 

  __init__()是一個執行個體方法,用來在執行個體建立完成後進行必要的初始化,該方法必須返回None.

  Python不會自動調用父類的__init__()方法,這需要額外的調用:

super(C, self).__init__()

 來完成。

 

 __del__(self) 

   在GC之前,Python會調用這個對象的__del__()方法完成一些終止化工作。如果沒有__del__()方法,那麼Python不做特殊的處理;

  Python無視__del__()方法的傳回值;

  Python不會自動調用父類的__del__()方法,除非顯式調用;

  定義了__del__()方法的執行個體無法參與到迴圈GC中,所以對於這樣的執行個體應該避免循環參考;

  try/finally語句或with語句可能是比__del__()更好的方式。

 

2. 表現形式

 __repr__(self) 

  Python內建的repr()函數,`x`運算式形式,或者互動式解譯器在顯示一個運算式語句的結果時,都調用這個對象的__repr__()方法;

  __repr__()方法返回的字串主要是面向解譯器的,改寫的話應該滿足: eval(repr(x)) == x 。

  如果沒有定義__repr__(),那麼Python使用一種預設的表現形式。

 

 __str__(self) 

  Python內建的1. str()函數,2. print(x)語句,都會調用對象的__str__()方法;

  與__repr__()返回的詳盡的、準確的、無歧義的對象描述字串不同,__str__()方法只是返回一個對應對象的簡潔的字串表達形式;

  當__str__()缺失時,Python會調用__repr__()方法;

  __str__()返回的字串應該是面向使用者的,可讀的。

 

 __unicode__(self) 

  Python內建的unicode(x)方法會調用__unicode__()方法;

  該方法如果定義,優先順序高於__str__()方法;

  同時定義這兩個方法的執行個體,調用它們的結果應該相同。

 

3. 比較、雜湊與布爾值

 __lt__(self, other) 

  x<y 運算將會調用執行個體x的__lt__(self, other)方法;

 

 __le__(self, other) 

  x<=y 運算將會調用執行個體x的__le__(self, other)方法;

 

 __gt__(self, other) 

  x>y 運算將會調用執行個體x的__gt__(self, other)方法;

 

 __ge__(self, other) 

  x>=y 運算將會調用執行個體x的__ge__(self, other)方法;

 

 __eq__(self, other) 

  x==y 運算將會調用執行個體x的__eq__(self, other)方法;

 

 __ne__(self, other) 

  x!=y 運算將會調用執行個體x的__ne__(self, other)方法;

  *上述用於執行個體間比較的特殊方法應該返回True或False,或者返回NotImplemented來告訴Python解譯器使用其他的方式進行比較。

 

 __cmp__(self, other) 

  對於上面提到的比較操作,如果對應的特殊方法沒有定義或者返回NotImplemented,則會調用__cmp__(self, other)再進行一次嘗試;

  一些內建的方法:cmp(x, y), max(x, y)或者列表對象的sort()方法也會調用__cmp__()方法;

  實現x.__cmp__()方法時,如果x小於y,應該返回-1,如果x大於y,應該返回1;如果x等於y,應該返回0.

  對於序列化比較(<, <=, >=, >),如果最終__cmp__()也沒有定義,那麼會拋出異常;

  對於相等與否的比較(==, !=),如果最終__cmp__()也沒有定義,將會變成身份檢驗:判斷id(x) == id(y)是否成立。

 

 __hash__(self) 

  三種情形會調用__hash__()方法:1. 內建的hash()方法,2.作為字典的鍵時,3.作為集合的成員時;

  __hash__()方法應該返回一個32位長的整數,對與同一個對象,__hash__()方法應該總是返回相同的值;對於 x == y ,即使二者不屬於相同的類型,只要他們是可雜湊的(hashable),都應該確保得到 hash(x) == hash(y) ;

  沒有 __hash__() 方法,也沒有 __cmp__() 和 __eq__() 方法,上面提到的三種情形將使用id(x)作為替代;

  沒有 __hash__() 方法,但是有 __cmp__() 和 __eq__() 方法,上面提到的前兩種方法會拋出異常;

  通常只為同時定義了 __cmp__()和/或__eq__() 方法的不可變(immutable)對象定義__hash__()方法,

  

 __nonzero__(self) 

  判斷一個對象是為真還是假時,例如調用bool(x)方法時,Python會調用x.__nonzero__(self)方法,__nonzero__()方法應該返回True或False。

  如果執行個體沒有__nonzero__()方法,那麼Python會調用執行個體的__len__()方法,當__len__()方法返回0時,Python認為該對象為假。所以如果執行個體沒有__nonzero__()方法與__len__()方法,則Python認為該執行個體總是真的;

  *所以以一個容器是否非空為判斷條件時,應該寫成:

if container:  pass

而不是:

if len(container) > 0 :  pass

因為後者將錯過__nonzero__()方法的檢驗。

 

4. 屬性的引用、綁定與解除綁定定

 __getattribute__(self, name) 

  訪問對象的屬性x.y時,Python會自動調用 x.__getattribute__(‘y‘) 方法;

  __getattribute__()方法應該返回被訪問的屬性的值或者是拋出異常 AttributeError ;

  覆寫類型的__getattribute__()方法會導致執行個體的屬性訪問變慢。

 

 __getattr__(self, name) 

  當常規的屬性訪問( x.__class__ 或 x.__dict__ 的鍵訪問)無法找到目標屬性時,Python會調用 __getattr__() 方法;

  如果該方法沒能找到目標屬性,應該拋出 AttributeError 。

 

 __setattr__(self, name, value) 

  綁定執行個體的某個屬性(賦值),例如 x.y = value 時,Python會自動調用 x.__setattr__(‘y‘, value) 方法;

  Python無視 __setattr__() 方法的傳回值;

  如果沒有定義 __setattr__() 方法,Python將賦值 x.y = value 解釋成 x.__dict__[‘y‘] = value 。

 

 __delattr__(self, name) 

  當解除綁定定一個對象的某個屬性(例如調用 del x.y )時,會調用 x.__delattr__(‘y‘) 方法;

  Python無視__delattr__()方法的傳回值;

  如果沒有定義__delattr__()方法,那麼Python將 del x.y 解釋成 del x.__dict__[‘y‘] 。

 

5. 可調用對象

 __call__(self[, args...]) 

   定義了該方法的對象可以像函數那樣被調用,因此被稱為可調用對象。

 

二 、容器的特殊方法

  容器可以是 序列(sequence) 或者 映射(mapping) 

 __contains__(self, item) 

  布爾測試 y in x 會調用 x.__contains__(y) ;

  對於序列x而言,如果y等於x中的某一個值,那麼__contains__()方法應該返回True;

  對於映射x而言,如果y等於x的鍵中的某一個,那麼__contains__()方法應該返回True;

  如果沒有定義__contains__()方法,那麼測試 y in x 等價於:

for z in x:    if y == z:        return True    else:        return False

 

 

 __delitem__(self, key) 

  從容器中解除綁定一個項或者切片(如 del x[key] )將會調用 x.__delitem__(key) 方法,

  只有可變對象才應該定義這個方法。

 

 __getitem__(self, key) 

  調用 x[key] (索引或切片)時將會調用 x.__getitem__(key) 方法;

 

 __iter__(self) 

  對於試圖遍曆一個容器的全部元素的請求(例如 for i in x ),Python將會調用 x.__iter__() 來獲得x上的一個迭代器;

  Python內建函數 iter(x) 也會調用 x.__iter__() 方法;

  如果沒有定義__iter__()方法,那麼iter(x)方法會合成並返回一個包含x的新的迭代器,然後逐個返回x中的元素;

  最好在每個容器中都實現__iter__()方法。

  

 __len__(self) 

  Python內建的 len(x) 調用或其他試圖得知x中的元素個數的函數都會最終調用 x.__len__() ;

  __len__()方法應該返回整形的數值;

  沒有定義__nonzero__()時,Python也會調用__len__()方法來判斷容器的真假;

  容器都應該定義__len__()方法,除非實現起來特別昂貴的情形。

  

 __setitem__(self, key, value) 

  對容器的一個元素或切片進行綁定(如: x[key] = value )時,Python會調用 x.__setitem__(key, value) ;

  可變(mutable)容器才應該定義該方法。

 

Python——特殊方法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.