Python 定制類的特殊方法

jopen 10年前發布 | 20K 次閱讀 Python Python開發

在定制類的過程中,添加的方法和屬性能完成大部分工作。但若想要類表現出一些特殊行為或者能夠響應某些內建函數或操作符,那么就需要構建一些特殊方法。這些特殊方法的標識是方法名以雙下劃線(__)開頭與結尾,除了常用的構造器 __init__() 外,還有一些常用的特殊方法。

基礎方法:

  • C.__new__(self[,arg1,…])        構造器(帶一些可選的參數);通常用在設置不可變數據類型的子類
  • C.__del__(self)        解構器
  • C.__str__(self)        可打印的字符串輸出;內建 str() 及 print() 函數
  • C.__repr__(self)        運行時的字符串輸出;內建 repr() 函數及 ' ' 操作符
  • C.__call__(self,*args)        用于可調用的實例;可以用來替代閉包的實現
  • C.__nonezero__(self)        為實例定義 False 值;內建 bool() 函數
  • C.__len__(self)        長度;內建 len()

類的值比較:

  • C.__cmp__(self,obj)        對象比較;內建 cmp()
  • C.__lt__(self,obj) & C.__le__(self,obj)        小于或小于等于;內建< & <=
  • C.__gt__(self,obj) & C.__ge__(self,obj)        大于或大于等于;內建 > & >=
  • C.__eq__(self,obj) & C.__ne__(self,obj)        等于或不等于;內建 = & !=

類的屬性:

  • C.__getattr__(self,attr)        獲取屬性;內建 getattr();僅在屬性沒有找到時調用
  • C.__setattr__(self,attr)        設置屬性
  • C.__delattr__(self,attr)        刪除屬性
  • C.__getattribute__(self,attr)        獲取屬性;內建 getattr();總是被調用
  • C.__get__(self,attr)        (描述符)獲取屬性
  • C.__set__(self,attr)        (描述符)設置屬性
  • C.__delete__(self,attr)        (描述符)刪除屬性

數值類型,二進制操作符:

  • C.__*add__(self,obj)        加;+ 操作符
  • C.__*sub__(self,obj)        減;+ 操作符
  • C.__*mul__(self,obj)        乘;* 操作符
  • C.__*dev__(self,obj)        除;/ 操作符
  • C.__*truediv__(self,obj)        真正的除法;/ 操作符
  • C.__*floordiv__(self,obj)        地板除;// 操作符
  • C.__*mod__(self,obj)        取模;% 操作符
  • C.__*divmod__(self,obj)        除和取模;內建 divmod()
  • C.__*pow__(self,obj[,mod])        乘冪;內建 pow() ; ** 操作符
  • C.__*lshift__(self,obj)        左移位;<< 操作符
  • C.__*rshift__(self,obj)        右移位;>> 操作符
  • C.__*and__(self,obj)        按位與;& 操作符
  • C.__*or__(self,obj)        按位或;| 操作符
  • C.__*xor__(self,obj)        按位異或;^ 操作符

數值類型,一元操作符:

  • C.__neg__(self)        一元負
  • C.__pos__(self)        一元正
  • C.__abs__(self)        絕對值;內建 abs()
  • C.__invert__(self)        按位求反;內建 ~ 操作符

數值類型,數值轉換:

  • C.__complex__(self, com)        內建 complex()
  • C.__int__(self)        內建 int()
  • C.__float__(self)        內建 float()

數值類型,數值壓縮:

  • C.__index__(self)        在有必要時,壓縮可選的數值類型為整型(比如用于切片索引時等)

序列類型:

  • C.__len__(self)        序列中的項目數
  • C.__getitem__(self, ind)        獲取一個元素
  • C.__setitem__(self, ind,val)        設置一個元素
  • C.__delitem__(self, ind)        刪除一個元素
  • C.__getslice__(self, ind1,ind2)        獲取切片元素
  • C.__setslice__(self, i1, i2,val)        設置切片元素
  • C.__delslice__(self, ind1,ind2)        刪除切片元素
  • C.__contains__(self, val)        含有成員;內建 in 關鍵字
  • C.__*add__(self,obj)        串聯;+ 操作符
  • C.__*mul__(self,obj)        重復;* 操作符
  • C.__iter__(self)        生成迭代器;內建 iter() 函數

映射類型:

  • C.__len__(self)        類中的項目數
  • C.__hash__(self)        散列(hash)函數值
  • C.__getitem__(self,key)        獲取某個值
  • C.__setitem__(self,key,val)        設置某個值
  • C.__delitem__(self,key)        刪除某個值
  • C.__missing__(self,key)        給定鍵若不存在,則返回一個默認值

一般常用的特殊方法就是上面這些,某些如 coerce() 這樣在 Python3 中被刪除或失效的內建函數就沒有再列出來。因為 Python 的內建類型已經能夠滿足日常需求,所以下面的例子就只來實現一個功能吧:雖然 float 類型有 .hex() 方法,但內建的 hex() 函數卻不支持 float 類型。所以我們來自定義一個可以被內建的 hex() 調用的浮點類型。為了省事,我們就直接從 float 派生了~

class iFloat(float):
    def __index__(self):
        return int(self)

運行結果如下:

>>> a = iFloat(1.1)
>>> hex(a)
'0x1'

P.S. 上面這個例子是個偽栗子。因為他實際是通過將浮點數強制轉換為整數來滿足調用 hex() 函數的條件的。按照官方文檔的說法,hex() 函數只接受 int 類型做參數,你在 iFloat 里實現 __hex__() 也沒用,這也是我把 __oct__() 和 __hex__() 從上面刪除的原因。同時按照官方文檔的說法,如果你硬要調用內建 hex() 函數,則必須實現 __index__() 方法來返回一個整數(是的,還是得要整數…)

即,下面這種方法是木有用的:

class iFloat(float):
    def __hex__(self):
        return self.hex()

仍然會報錯,盡管 __hex__(self) 可以返回正常值:

>>> a = iFloat(1.1)
>>> hex(a)
Traceback (most recent call last):
  File "<pyshell#31>", line 1, in <module>
    hex(a)
TypeError: 'iFloat' object cannot be interpreted as an integer
>>> a.__hex__()
'0x1.199999999999ap+0'

覺得這可能是因為內建 hex() 函數已經不只是調用 __hex__() 這么簡單了。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!