User: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
对象具有三个只读属性 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 索引用作列表、元组和字符串时,总是返回子列表、子元组和子字符串。
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
对象”的逗号运算符。