chapter9.1、魔術方法
魔術方法
python精華之一
特殊屬性
__name__ 類,函式,方法等的名字
__modle__ 主模組,當前的模組__main__,其他模組呼叫返回模組物件
__class__ 相當於type,物件或類所屬的類
__bases__ 返回基類的元組,順序為基類列表中出現的順序
__doc__ 文件,未定義為None
__mro__ 類的mro,定義時就會計算並放在類的屬性裡的__mro__中
__dict__ 類或例項的屬性,可寫的字典,這裡注意有些只讀字典
檢視屬性
__dir__ 返回類的或者物件的所有成員的列表,
dir()函式呼叫__dir__(),dir是內建函式,
如果類中和例項中定義了__dir__:
使用例項呼叫時,例項中如果定義了__dir__,就會覆蓋類__dir__,返回例項中的__dir__的執行結果;
如果例項中沒有,就會呼叫父類的,如果父類沒有,就繼續向上找,中間有的話就會執行該方法;
如果類中和例項中沒有定義__dir__:
如果物件是模組物件,返回的列表包含檔案的屬性名和變數名,受作用域影響,一般在模組上使用時,呼叫模組,在自己的模組蒐集
如果物件是類或類的例項,近似於自己例項的字典加類的字典加object的字典,返回列表包含類的屬性名,及它的基類的屬性名
如果dir() 括號中不寫,返回的列表包含不同的內容
在模組中,返回模組的屬性和變數名
在函式中,返回本地作用域的變數名
在函式中,返回本地作用域的變數名
魔術方法
建立,初始化與銷燬
__new__ 例項化,可以不寫,會去調父類的方法。一定要return,返回不要再調自己,調本型別的例項,如果不是cls的例項,就不會呼叫__init__,即使建立了該方法,也會使用return super().__new__(cls), 最後呼叫的是object的__new__方法建立並返回例項
__init__
__del__
__hash__ 內建函式hash()呼叫後的返回值,返回整數,現在Linux的加密主要使用的MD5演算法也是hash演算法的一種,
雜湊演算法,具有冪等性,同一個程式中不論計算多少次,相同的物件返回的hash的值都一樣,
不同的hash演算法,可能會產生hash衝突,不同的x可能求得同樣的值
__eq__ 判斷是否相同,返回一個bool值,hash函式只負責計算hash,去重需要__eq__判斷,
一般hash只要不衝突,就不會呼叫__eq__,__eq__ 對應 '==' 操作符,判斷兩個物件是否相等,返回bool。
一旦類中提供__eq__ ,類中就會自動新增__hash__=None
hash值相等不代表物件相等,
list類的例項不可hash,在list類中,原始碼中有__hash__ = None,也就是說如果呼叫__hash__相當於呼叫None,
如果你建立的類不能被hash,那就把__hash__設定為None
import math class Point: def __init__(self, x, y): self.x = x self.y = y def __hash__(self): return hash((self.x, self.y)) def __eq__(self, obj): return self.x == obj.x and self.y == obj.y p1 = Point(3, 0) p2 = Point(0, 4) p3 = Point(3, 0) print({p1, p2, p3})##可以去重
__bool__ 內建函式bool(),或者物件放在邏輯表示式的位置,呼叫這個函式返回布林值
沒有定義__bool__()的,就去__len__()返回長度,非零為真
視覺化方法
__repr__ 內建函式repr()對一個物件獲取字串表達,
呼叫__repr__方法返回字串,間接呼叫會調,如果未定義,直接返回object的定義,也就是顯示記憶體地址的資訊
__str__ 例項直接print(),或者str(),或者format(),呼叫時,要返回物件的字串表達,
如果沒有定義,就去呼叫__repr__方法返回字串表示式,如果沒有__repr__定義,就直接返回物件的記憶體地址
類不提供__str__,就使用__repr__;不提供__repr__就去object找,
要注意:列印物件,輸出形式,打印出來的型別不作數,並不能真正的表達物件的型別!
__bytes__ 提供bytes方法,bytes()函式呼叫,返回一個物件的bytes表達,即返回bytes物件
運算子過載
< __lt__ 小於 lessthan
<= __le__ 小於等於 lessequal
> __gt__ 大於 greatthan
>= __ge__ 大於等於 greatequal
== __eq__ 等於 equal ,只有==才呼叫
!= __ne__ 不等於 notequal
+ - * / __add__ ,__sub__ ,__mul__ ,__truediv__ 加減乘除過載
% __mod__ 取模運算過載
// __floordiv__ 整除過載
** __pow__ 乘方過載
divmod __divmod__ 取模取餘
+= ,-= , *= , /= , %= , //= , **= __iadd__ , __isub__ , __imul__ , itruediv__ , __imod__ , __ifloordiv__ , __ipow__ ,其中的 i 表示in place,立即返回
如果不定義加等,就去調add,在賦值給左邊的值,其他的運算也是
例項之間的計算,可以用座標點來理解
import math
class Point: def __init__(self,x,y): self.x = x self.y = y def __eq__(self,obj): return self.x ==obj.x and self.y == obj.y def __add__(self,other): return Point(self.x + other.x,self.y+other.y) def __sub__(self,other): return Point(self.x - other.x,self.y-other.y) def __repr__(self): return "({},{})".format(self.x,self.y)
還可以使用total ordering 模組,但是要提供等於和大小與四種之中的一種,一般自己寫,寫三個,等於,大小於中的一個,和大於小於中的一個,就可以推斷另一個
大於推斷小於
等於推斷不等於
大於等於推斷小於等於
用total ordering 可能產生效能問題,儘量自己寫,
類的大量運算,運算子是較常見的表達方式,提供運算子過載比提供加法方式更符合使用者的習慣
可參見int的所有的操作符,幾乎實現了所有的操作符
容器相關方法
__len__ 內建函式len(),返回物件的長度(>=0),將物件看作容器,bool()函式呼叫時,沒有__bool__屬性時,就會來判斷__len__是否存在,如果存在且不為0,就返回真
__iter__ 迭代容器內容時,返回一個迭代器物件
__contains__ in成員運算子,沒有實現,就調__iter__遍歷,查詢都要遍歷,可以不寫contains
__getitem__ 實現self [ key ] 訪問,如果是序列物件,key就是整數索引,或者是切片,對於字典和集合,key是hashable的,不存在就KeyError
__setitem__ 和getitem訪問類似,是設定值的方法
__missing__ 字典和類使用時,__getitem__()呼叫key不存在時執行