用戶: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 文檔

參考文獻[編輯 | 編輯原始碼]