漫談Python魔術方法,見過的沒見過的都在這裡了
就說一下,不深入
假的一覽
- 提到魔術方法,學過python都應該知道一些。至少你得會__init__吧。
- 在我之前寫的博文中有很多都涉及魔術方法。比如
- 在《Python原始碼剖析》中做了個簡單的概括(侵刪),但仍然是不全的
資料模型
https://docs.python.org/zh-cn/3.9/reference/datamodel.html
以3.9為例
- 最全的還是在官方(但仍然會有漏網之魚)
- 我稍作整理,僅供參考
1. ★基本客製化
方法 |
說明 |
__init__(self[, ...]) |
所謂的初始化,在範例 (通過__new__ ) 被建立之後,返回撥用者之前呼叫 |
__new__(cls[, ...]) |
呼叫以建立一個 cls 類的新範例 |
__del__(self) |
在範例將被銷燬時呼叫。 這還被稱為終端子或解構器(不適當) |
__repr__(self) |
由 repr() 內建函數呼叫以輸出一個物件的「官方」字串表示 |
__str__(self) |
通過 str(object) 以及內建函數 format() 和 print() 呼叫以生成一個物件的「非正式」或格式良好的字串表示 |
__bytes__(self) |
通過 bytes 呼叫以生成一個物件的位元組串表示 |
__format__(self,format_spec) |
通過 format() 內建函數、擴充套件、格式化字串字面值 的求值以及 str.format() 方法呼叫以生成一個物件的「格式化」字串表示 |
__hash__(self) |
通過內建函數 hash() 呼叫以對雜湊集的成員進行操作,屬於雜湊集的型別包括 set、frozenset 以及 dict。__hash__() 應該返回一個整數 |
__bool__(self) |
呼叫此方法以實現真值檢測以及內建的 bool() 操作;應該返回 False 或 True |
2. 富比較方法
方法 |
說明 |
__lt__(self, other) |
小於 |
__le__(self, other) |
小於等於 |
__eq__(self, other) |
等於 |
__ne__(self, other) |
不等於 |
__gt__(self, other) |
大於 |
__ge__(self, other) |
大於等於 |
3. ★自定義屬性存取
方法 |
說明 |
__getattr__(self, name) |
當預設屬性存取因引發 AttributeError 而失敗時被呼叫 |
__getattribute__(self, name) |
此方法會無條件地被呼叫以實現對類範例屬性的存取 |
__setattr__(self, name, value) |
此方法在一個屬性被嘗試賦值時被呼叫 |
__delattr__(self, name) |
類似於 __setattr__() 但其作用為刪除而非賦值 |
__dir__(self) |
此方法會在對相應物件呼叫 dir() 時被呼叫 |
|
|
4. ★實現描述器
方法 |
說明 |
__get__(self, instance, owner=None) |
呼叫此方法以獲取所有者類的屬性(類屬性存取)或該類的範例的屬性(範例屬性存取) |
__set__(self, instance, value) |
用此方法以設定 instance 指定的所有者類的範例的屬性為新值 value。 |
__delete__(self, instance) |
呼叫此方法以刪除 instance 指定的所有者類的範例的屬性。 |
__set_name__(self, owner, name) |
在所有者類 owner 建立時被呼叫。描述器會被賦值給 name。 |
|
|
5. 自定義類建立
方法 |
說明 |
__init_subclass__(cls) |
當所在類派生子類時此方法就會被呼叫 |
6. 自定義範例及子類檢查
方法 |
說明 |
__instancecheck__(self, instance) |
如果 instance 應被視為 class 的一個(直接或間接)範例則返回真值 |
__subclasscheck__(self, subclass) |
如果 subclass 應被視為 class 的一個(直接或間接)子類則返回真值 |
|
|
|
|
7. 模擬泛型型別
方法 |
說明 |
__class_getitem__(cls, key) |
按照 key 引數指定的型別返回一個表示泛型類的專門化物件。 |
- 當在類上定義時,
__class_getitem__()
會自動成為類方法。 因此,當它被定義時沒有必要使用 @classmethod
來裝飾。
8. ★模擬可呼叫物件
方法 |
說明 |
__call__(self[, args...]) |
此方法會在範例作為一個函數被「呼叫」時被呼叫 |
9. ★模擬容器型別
方法 |
說明 |
__len__(self) |
呼叫此方法以實現內建函數 len()。應該返回物件的長度 |
__length_hint__(self) |
呼叫此方法以實現 operator.length_hint()。 應該返回物件長度的估計值(可能大於或小於實際長度) |
__getitem__(self, key) |
呼叫此方法以實現 self[key] 的取值(注:官文是未付,英文是evaluation) |
__setitem__(self, key, value) |
呼叫此方法以實現向 self[key] 賦值 |
__delitem__(self, key) |
呼叫此方法以實現 self[key] 的刪除 |
__missing__(self, key) |
此方法由 dict.__getitem__() 在找不到字典中的鍵時呼叫以實現 dict 子類的 self[key] |
__iter__(self) |
此方法在需要為容器建立迭代器時被呼叫 |
__reversed__(self) |
此方法(如果存在)會被 reversed() 內建函數呼叫以實現逆向迭代 |
__contains__(self, item) |
呼叫此方法以實現成員檢測運運算元in |
10. ★模擬數位型別
方法 |
說明 |
__add__(self, other) |
+ |
__sub__(self, other) |
- |
__mul__(self, other) |
* |
__matmul__(self, other) |
@這個你可能沒聽過 |
__truediv__(self, other) |
除法 / |
__floordiv__(self, other) |
地板除 // |
__mod__(self, other) |
取餘 % |
__pow__(self, other[,modulo]) |
冪運算 ** |
__lshift__(self, other) |
左移 << |
__rshift__(self, other) |
右移 >> |
__and__(self, other) |
& 與 |
__xor__(self, other) |
^ 互斥或 |
__or__(self, other) |
| 或 |
|
|
方法 |
說明 |
__radd__(self, other) |
+ |
__rsub__(self, other) |
- |
__rmul__(self, other) |
* |
__rmatmul__(self, other) |
@ |
`rtruediv(self, other) |
/ |
__rfloordiv__(self, other) |
// |
__rmod__(self, other) |
取餘 % |
__rpow__(self, other[,modulo]) |
冪運算 ** |
__rlshift__(self, other) |
左移 << |
__rrshift__(self, other) |
右移 >> |
__rand__(self, other) |
& |
__rxor__(self, other) |
^ |
__ror__(self, other) |
| |
|
|
-
呼叫這些方法來實現具有反射(交換)運算元的二進位制算術運算 (+
, -
, *
, @
, /
, //
, %
, divmod()
, pow()
, **
, <<
, >>
, &
, ^
, |
)。這些成員函數僅會在左運算元不支援相應運算 3 且兩個運算元型別不同時被呼叫。4 例如,求表示式 x - y
的值,其中 y 是具有 __rsub__()
方法的類的一個範例,則當 x.__sub__(y)
返回 NotImplemented 時會呼叫 y.__rsub__(x)
。
請注意三元版的 pow()
並不會嘗試呼叫 __rpow__()
(因為強制轉換規則會太過複雜)
方法 |
說明 |
__iadd__(self, other) |
+= |
__isub__(self, other) |
-= |
__imul__(self, other) |
*= |
__imatmul__(self, other) |
@= |
__itruediv__(self, other) |
/= |
__ifloordiv__(self, other) |
//= |
__imod__(self, other) |
%= |
__ipow__(self, other[,modulo]) |
**= |
__ilshift__(self, other) |
<<= |
__irshift__(self, other) |
>>= |
__iand__(self, other) |
&= |
__ixor__(self, other) |
^= |
__ior__(self, other) |
|= |
|
|
方法 |
說明 |
__neg__(self) |
一元運運算元 - |
__pos__(self) |
一元運運算元 + |
__abs__(self) |
abs() |
__invert__(self) |
一元運運算元 ~ |
__complex__(self) |
實現內建函數complex() |
__int__(self) |
實現內建函數int() |
__float__(self) |
實現內建函數float() |
__index__(self) |
呼叫此方法以實現 operator.index() |
__round__(self[,ndigits]) |
實現內建函數round() |
__trunc__(self) |
實現內建函數trunc() |
__floor__(self) |
實現內建函數floor() |
__ceil__(self) |
實現內建函數ceil() |
|
|
|
|
11. 上下文管理器
方法 |
說明 |
__enter__(self) |
進入與此物件相關的執行時上下文 |
__exit__(self, exc_type, exc_value, traceback) |
退出關聯到此物件的執行時上下文 |
12. 協程相關
可等待物件
方法 |
說明 |
__await__(self) |
awaitable 物件主要實現了該方法,它必須返回一個 iterator |
|
|
非同步迭代器
方法 |
說明 |
__aiter__(self) |
必須返回一個 非同步迭代器 物件 |
__anext__(self) |
必須返回一個 可迭代物件 輸出迭代器的下一結果值 |
非同步上下文管理器
方法 |
說明 |
__aenter__(self) |
在語意上類似於 __enter__() ,僅有的區別是它必須返回一個 可等待物件 |
__aexit__(self) |
在語意上類似於 __exit__() ,僅有的區別是它必須返回一個 可等待物件 |
00. 漏網之魚
方法 |
說明 |
__objclass__ |
會被 inspect 模組解讀為指定此物件定義所在的類 |
__slots__ |
允許我們顯式地宣告資料成員(如特徵屬性)並禁止建立 dict 和 weakref |
__mro_entries__ |
|
__prepare__ |
|
__class__ |
|
__classcell__ |
|
說在最後
-
碼農高天出了一個系列講解魔術方法,推薦觀看https://www.bilibili.com/video/BV1b84y1e7hG
-
流暢的python對魔術方法的講解比較深入,貫穿全文,有一定難度,基礎薄弱的謹慎
-
前面在哪裡說過很多內建函數、操作、運運算元的背後多數都是這些魔術方法的實現。
- with上下文管理器的背後是
__enter__(self)
和__exit__(self, exc_type, exc_value, traceback)
- 多數的運運算元背後都是的10. 模式數位型別
- 內建函數如len的背後是
__len__