切片是 python 中最迷人最強大最 amazing 的語言特性(幾乎沒有之一),在《python高階:切片的誤區與高階用法》中,我介紹了切片的基礎用法、高階用法以及一些使用誤區。這些內容都是基於原生的序列型別(如字串、列表、元組......),那麼,我們是否可以定義自己的序列型別並讓它支援切片語法呢?更進一步,我們是否可以自定義其它物件(如字典)並讓它支援切片呢?
想要使自定義物件支援切片語法並不難,只需要在定義類的時候給它實現魔術方法__getitem__()
即可。所以,這裡就先介紹一下這個方法。
語法:object.__getitem__(self, key)
概括翻譯一下:__getitem__()
方法用於返回引數 key 所對應的值,這個 key 可以是整型數值和切片物件,並且支援負數索引;如果 key 不是以上兩種型別,就會拋 typeerror;如果索引越界,會拋 indexerror ;如果定義的是對映型別,當 key 引數不是其物件的鍵值時,則會拋 keyerror 。
接下來,我們定義乙個簡單的 mylist ,並給它加上切片功能。(ps:僅作演示,不保證其它功能的完備性)。
class mylist():
def __init__(self):
self.data =
def __getitem__(self, key):
print("key is : " + str(key))
return self.data[key]
l = mylist()
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 = " indices must be integers"
raise typeerror(msg.format(cls=cls))
切片是序列型別的特性,所以在上例中,我們不需要寫切片的具體實現邏輯。但是,對於其它非序列型別的自定義物件,就得自己實現切片邏輯。以自定義字典為例(ps:僅作演示,不保證其它功能的完備性):
class mydict():
def __init__(self):
self.data = {}
def __len__(self):
return len(self.data)
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
else:
raise typeerror
d = mydict()
print(d[2])
print(d[:2])
print(d[-4:-2])
print(d['hi'])
### 輸出結果:
istraceback (most recent call last):
...typeerror
上例的關鍵點在於將字典的鍵值取出,並對鍵值的列表做切片處理,其妙處在於,不用擔心索引越界和負數索引,將字典切片轉換成了字典鍵值的切片,最終實現目的。
最後小結一下:本文介紹了__getitem__()
魔術方法,並用於實現自定義物件(以列表型別和字典型別為例)的切片功能,希望對你有所幫助。
Python高階 自定義物件實現切片功能
切片是 python 中最迷人最強大最 amazing 的語言特性 幾乎沒有之一 在 python高階 切片的誤區與高階用法 中,我介紹了切片的基礎用法 高階用法以及一些使用誤區。這些內容都是基於原生的序列型別 如字串 列表 元組.那麼,我們是否可以定義自己的序列型別並讓它支援切片語法呢?更進一步,...
python高階 自定義庫函式
在python使用過程中,在不同的專案裡,常常會出現頻繁地自定義同乙個函式的情況。為了解決這個問題,我們可以選擇建立乙個自定義的庫,並將其新增到系統路徑中 具體操作如下 在任意位置新建乙個專案my libs,並在其中新建python檔案my lib1和my lib2,將需要自定義的函式在my lib...
物件陣列。自定義物件
定義學生類屬性 自定義方法 顯示學生資訊方法年齡增加方法測試類 建立用於儲存學生的陣列,長度為5,建立5個學生物件,將物件儲存到陣列中遍歷陣列中的學生物件,分別呼叫年齡增加方法,將學生年齡增加2遍歷陣列中的學生物件,分別呼叫顯示資訊的方法,檢視所有學生資訊查詢年齡大於20的學生資訊 針對這個作業。寫...