用戶:Xyy23330121/Python/類的方法與Python的計算/對索引為slice對象的支持
外觀
本頁面將討論對索引為 slice 對象時,應如何設計 __getitem__
方法。並最終給出一個簡單的實現。
當然,如果讀者想要不按照常規、讓 __getitem__
根據輸入的 slice
隨意輸出一個結果。當然也是可以的。
slice 對象可以由slice(start, stop, step=None)
或 slice(stop)
[1]的方式給出。我們可以用以下方式確認:傳入「索引」參數的確實是 slice 對象。
class getSlice:
def __getitem__(self, key):
return key
get = getSlice()
print(obj[0:5:2]) #输出:slice(0, 5, 2)
print(obj[0:5:2] == slice(0,5,2)) #输出:True
與用作索引時不同,用 slice
函數創建 slice 對象時一定要傳入 stop
參數。
slice
對象具有三個只讀屬性 start
、stop
和 step
。這三個屬性,對於索引的實現很有幫助。如以下示例:
class getSlice:
def __getitem__(self, key): return key
a = get[:]
b = get[0:]
c = get[0:5:1]
print(a.start,a.stop,a.step) #输出:None None None
print(b.start,b.stop,b.step) #输出:0 None None
print(c.start,c.stop,c.step) #输出:0 5 1
可以看出,在使用索引時,如果不輸入對應位置的內容,則會直接傳入 None
。在進行 slice
對象支持時,一定要注意對 None
的處理。
slice 索引用作列表、元組和字符串時,總是返回子列表、子元組和子字符串。
slice 索引在 start 或 end 超出整數索引範圍時也能使用。
slice 索引在 start >= end and step > 0 時返回空的容器;在 start <= end and step < 0 時也返回空的容器。
如果不希望考慮那麼多內容,讀者也可以簡單一點。注意到以下代碼可以直接輸出所需的對應索引序列:
(i for i in range(len(self)))[key]
我們可以先支持用可迭代序列作索引,再把slice
,用 Python 已有的方法直接轉換為可迭代序列。
from collections.abc import Iterator
class MyClass:
...
def __getitem__(self, key):
#对可迭代序列作索引的支持
if isinstance(key, Iterator):
return MyClass([self[i] for i in key])
#直接把 slice 用(0,1,...)[slice]的方式转化为可迭代序列。
if isinstance(key, slice):
return self[(i for i in range(len(self)))[key]]
...
raise ValueError("不被支持的索引类型。")
def __len__(self):
...
具體來講,可以把 :
當成「只有在索引的方括號中才可用的運算符」。該運算符結合其左右的內容,生成 slice
對象。我們看以下例子:
class getSlice:
def __getitem__(self, key): return key
get = getSlice()
print(get[:,:]) #(slice(None, None, None), slice(None, None, None))
可以看出,該運算符的優先級高於「生成 tuple
對象」的逗號運算符。