用戶:Xyy23330121/Python/類的方法與Python的計算
學習了「類」之後,我們可以進一步了解 Python 的數據模型:Python 中一切內容、包括計算在內,都是由類和類的實例完成的。
以簡單的 len(s)
為例,我們查閱文檔,可以發現它實際上是調用了 s
的方法 s.__len__(self)
,並返回該方法的結果[1]。
甚至,連加減法在內,幾乎所有的 Python 運算都可以用類的方法來定義、修改。為篇幅起見,本頁面的內容被分為多個頁面。讀者可以在右側目錄中找到對應頁面。
可調用類型
編輯object.__call__(self[, ...])
編輯此方法用於支持把對象當函數使用時的結果。我們看以下示例:
class prt:
def __call__(self, *arg):
print(*arg)
a = prt()
a(11,45,14) #输出:11 45 14
它除了第一個參數會自動傳入自身以外,與平常定義的函數基本沒有區別。
容器類型
編輯長度
編輯len
函數時可能會產生困惑。此方法用於支持 len(self)
。該方法必須返回對象的長度,並必須以一個非負的 int
類型來表示。如果返回的並非非負整數,則會報錯。
特別的,如果一個對象沒有定義 __bool__
方法,而其 __len__
方法返回的值為 0
。則它在布爾運算中,被視為 False
。
operator
模塊中,operator.length_hint()
函數所調用的方法。
此方法是為了優化性能而設置的,它必須返回對象長度的估計值——這個估計值並不要求正確無誤。返回的估計值必須為一個非負整數。
特別的,返回值也可以為 NotImplemented,這會被視作與 __length_hint__ 方法完全不存在時一樣處理。
索引
編輯object.__getitem__(self, key)
編輯此方法用於支持 self[key]
的操作。一般用於鍵的有三種:
- 整數(用於序列)
- slice 對象(用於序列)
- 字符串或其它不可變對象(主要用於字典)。
此方法的返回值,應當為讀者希望 self[key]
所返回的數值。和其它強制進行類型檢查的方法不同,此方法實際上可以返回任何值。
object.__setitem__(self, key, value)
編輯此方法用於支持 self[key] = value
的操作。在調用此方法時,應直接對 self
進行修改。
object.__delitem__(self, key)
編輯此方法用於支持 del self[key]
的操作。
slice 對象
編輯在字符串章節,提到過 slice 索引。slice 對象就是用該種索引方式時,向 key
參數傳入的對象。
索引與錯誤處理
編輯如果 key 的類型不正確,則應當引發 TypeError。 如果 key 為序列索引集合範圍以外的值(在進行任何負數索引的特殊解讀之後),則應當引發 IndexError。 對於 mapping 類型,如果 key 找不到(不在容器中),則應當引發 KeyError。
解決 str.format 的問題
編輯於是,解決 str.format
中,不支持負數索引和 slice 索引的方式是簡單的。使用:
class fixGetitem:
def __init__(self, obj):
self.obj = obj
def __getitem__(self, key):
if isinstance(key, str):
if ':' in key:
key_list = [(int(arg) if arg != "" else None) for arg in key.split(':')]
if len(key_list) == 2:
return self.obj[key_list[0]: key_list[1]]
return self.obj[key_list[0]: key_list[1]: key_list[2]]
return self.obj[int(key)]
return self.obj[key]
在傳入 str.format
的參數 s
時,如果有負數索引或 slice 索引的需要(且沒有字符串索引的需要時),直接改為傳入 fixGetitem(s)
就能解決該問題。讀者可以自行拓展此方法。
object.__missing__(self, key)
編輯對於 dict 的子類,如果定義了該方法。則在 __getitem__(key)
找不到鍵 key
時,會嘗試調用 __missing__(key)
並返回 __missing__(key)
的值。
迭代
編輯object.__iter__(self)
編輯該方法應該且必須返回一個新的迭代器對象。如果不返回迭代器,則會報錯。
此方法可用於支持 iter
函數、for ... in
語句以及比較運算符 in
和 not in
。
object.__reversed__(self)
編輯該方法用於提升 reversed(self)
的效率和 / 或適用範圍。
如果定義了該方法,則該方法必須返回一個新的迭代器對象。它應當返回以逆序逐個迭代容器內所有對象的迭代器對象。
如果未定義該方法,則 reversed(self)
會使用 __len__
方法和 __getitem__
方法,按照類似列表的方式生成一個迭代器。
成員檢測
編輯object.__contains__(self, item)
編輯此方法用於支持 item in self
和 item not in self
。它返回一個布爾值。
如果未定義 __contains__
方法。上述運算將嘗試通過 __iter__
來迭代 self
中的元素來實現。
泛型
編輯對於類型,我們也有類似索引的操作。泛型就是這種操作的結果。
泛型一般用於函數註釋中。具體參見 函數註釋#泛型 。
classmethod object.__class_getitem__(cls, key)
編輯獲取泛型時調用的方法。這個方法會自動被視為是類方法,因此沒必要使用裝飾符 @classmethod
來裝飾。
此方法一般不由讀者定義,而是通過繼承的方式自動引入的。具體可以參見Python 文檔。