跳至內容

使用者:Xyy23330121/Python/類的方法與Python的計算/對索引為slice對象的支持

來自維基學院

本頁面將討論對索引為 slice 對象時,應如何設計 __getitem__ 方法。並最終給出一個簡單的實現。

當然,如果讀者想要不按照常規、讓 __getitem__ 根據輸入的 slice 隨意輸出一個結果。當然也是可以的。

創建 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 作為索引的要點[編輯 | 編輯原始碼]

slice 對象的屬性[編輯 | 編輯原始碼]

slice 對象具有三個只讀屬性 startstopstep。這三個屬性,對於索引的實現很有幫助。如以下示例:

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 索引用作列表、元組和字符串時,總是返回子列表、子元組和子字符串。

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 對象」的逗號運算符。

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