本篇文章帶給大家的內容是關於Python自訂物件實現切片功能的介紹(程式碼範例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
1、魔術方法:__getitem__()
#想要讓自訂物件支援切片語法並不難,只需要在定義類別的時候給它實作魔術方法__getitem__()
即可。所以,這裡就先介紹一下這個方法。
語法: object.__getitem__(self, key)
官方文件釋義:Called to implement evaluation of self[key]. For sequence types, the accepted keys should be integers and slice objects. Note that the special interpretation of negative indexes (if the class wishes to emulate a sequence type) is up to the __getitem__() method. If key is of an inappropriate type, TypeError may be raised; if of a value outside the set of indexes for the sequence (after any special interpretation of negative values), IndexError should be raised. For mapping types, if key is missing (not in the container), KeyError should be raised.
概括翻譯一下:__getitem__() 方法用來傳回參數 key 所對應的值,這個 key 可以是整數數值和切片對象,並且支援負數索引;如果 key 不是以上兩種類型,就會拋 TypeError;如果索引越界,會拋 IndexError ;如果定義的是映射類型,當 key 參數不是其物件的鍵值時,則會拋 KeyError 。
2、自訂序列實作切片功能
接下來,我們定義一個簡單的 MyList ,並為它加上切片功能。 (PS:僅作演示,不保證其它功能的完備性)。
class MyList(): def __init__(self): self.data = [] def append(self, item): self.data.append(item) def __getitem__(self, key): print("key is : " + str(key)) return self.data[key] l = MyList() l.append("My") l.append("name") l.append("is") l.append("Python猫") print(l[3]) print(l[:2]) print(l['hi']) ### 输出结果: key is : 3 Python猫 key is : slice(None, 2, None) ['My', 'name'] key is : hi Traceback (most recent call last): ... TypeError: list indices must be integers or slices, not str
從輸出結果來看,自訂的 MyList 既支援依索引查找,也支援切片運算,這正是我們的目的。
特別需要說明的是,此範例中的 __getitem__() 方法會根據不同的參數類型而實現不同的功能(取索引位值或切片值),也會妥當地處理異常,所以並不需要我們再寫繁瑣的處理邏輯。網路上有不少學習資料完全是在誤人子弟,它們會教你區分參數的不同類型,然後寫一大段程式碼來實現索引查找和切片語法,簡直是畫蛇添足。下面的就是一個代表性的錯誤範例:
###略去其它代码#### def __getitem__(self, index): cls = type(self) if isinstance(index, slice): # 如果index是个切片类型,则构造新实例 return cls(self._components[index]) elif isinstance(index, numbers.Integral): # 如果index是个数,则直接返回 return self._components[index] else: msg = "{cls.__name__} indices must be integers" raise TypeError(msg.format(cls=cls))
3、自訂字典實作切片功能
切片是序列類型的特性,所以在上例中,我們不需要寫切片的具體實作邏輯。但是,對於其它非序列類型的自訂對象,就得自行實現切片邏輯。以自訂字典為例(PS:僅作演示,不保證其它功能的完備性):
class MyDict(): def __init__(self): self.data = {} def __len__(self): return len(self.data) def append(self, item): self.data[len(self)] = item def __getitem__(self, key): if isinstance(key, int): return self.data[key] if isinstance(key, slice): slicedkeys = list(self.data.keys())[key] return {k: self.data[k] for k in slicedkeys} else: raise TypeError d = MyDict() d.append("My") d.append("name") d.append("is") d.append("Python猫") print(d[2]) print(d[:2]) print(d[-4:-2]) print(d['hi']) ### 输出结果: is {0: 'My', 1: 'name'} {0: 'My', 1: 'name'} Traceback (most recent call last): ... TypeError
上例的關鍵點在於將字典的鍵值取出,並對鍵值的列表做切片處理,其妙處在於,不用擔心索引越界和負數索引,將字典切片轉換成了字典鍵值的切片,最終實現目的。
4、小結
最後小結一下:本文介紹了__getitem__() 魔術方法,並用於實作自訂物件(以列表類型和字典類型為例)的切片功能,希望對你有幫助。
#以上是Python自訂物件實作切片功能的介紹(程式碼範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!