使用者: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 函數時可能會產生困惑。

object.__len__(self)[1]

編輯

此方法用於支持 len(self)。該方法必須返回對象的長度,並必須以一個非負的 int 類型來表示。如果返回的並非非負整數,則會報錯。

特別的,如果一個對象沒有定義 __bool__方法,而其 __len__ 方法返回的值為 0。則它在布爾運算中,被視為 False

object.__length_hint__(self)[2]

編輯

operator 模塊中,operator.length_hint()函數所調用的方法。

此方法是為了優化性能而設置的,它必須返回對象長度的估計值——這個估計值並不要求正確無誤。返回的估計值必須為一個非負整數。

特別的,返回值也可以為 NotImplemented,這會被視作與 __length_hint__ 方法完全不存在時一樣處理。

索引

編輯

object.__getitem__(self, key)

編輯

此方法用於支持 self[key] 的操作。一般用於鍵的有三種:

  1. 整數(用於序列)
  2. slice 對象(用於序列)
  3. 字符串或其它不可變對象(主要用於字典)。

此方法的返回值,應當為讀者希望 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 語句以及比較運算符 innot in

object.__reversed__(self)

編輯

該方法用於提升 reversed(self) 的效率和 / 或適用範圍。

如果定義了該方法,則該方法必須返回一個新的迭代器對象。它應當返回以逆序逐個迭代容器內所有對象的迭代器對象。

如果未定義該方法,則 reversed(self) 會使用 __len__ 方法和 __getitem__ 方法,按照類似列表的方式生成一個迭代器。

成員檢測

編輯

object.__contains__(self, item)

編輯

此方法用於支持 item in selfitem not in self。它返回一個布爾值。

如果未定義 __contains__ 方法。上述運算將嘗試通過 __iter__ 來迭代 self 中的元素來實現。

泛型

編輯

對於類型,我們也有類似索引的操作。泛型就是這種操作的結果。

泛型一般用於函數注釋中。具體參見 函數注釋#泛型

classmethod object.__class_getitem__(cls, key)

編輯

獲取泛型時調用的方法。這個方法會自動被視為是類方法,因此沒必要使用裝飾符 @classmethod 來裝飾。

此方法一般不由讀者定義,而是通過繼承的方式自動引入的。具體可以參見Python 文檔

參考文獻

編輯