实现 __getitem__ 方法

4 投票
1 回答
1147 浏览
提问于 2025-04-17 20:38

有没有办法实现 __getitem__ 这个功能,让它既能处理整数索引,也能处理切片索引,而不需要手动检查传入参数的类型呢?

我看到很多这样的例子,但对我来说,这种做法感觉很不靠谱。

def __getitem__(self,key):
  if isinstance(key,int):
    # do integery foo here
  if isinstance(key,slice):
    # do slicey bar here

顺便问一下,为什么会有这个问题呢?有时候返回一个整数,有时候又返回一个切片,这种设计感觉很奇怪。调用 foo[4] 应该直接调用 foo.__getitem__(slice(4,5,1)) 或者类似的东西。

1 个回答

5

你可以使用异常处理;假设 key 是一个 slice 对象,然后调用它的 indices() 方法。如果这个调用失败了,那说明它应该是一个整数。

def __getitem__(self, key):
    try:
        return [self.somelist[i] * 5 for i in key.indices(self.length)]
    except AttributeError:
        # not a slice object (no `indices` attribute)
        return self.somelist[key] * 5

大多数 自定义容器的使用场景其实不需要支持切片操作,历史上,__getitem__ 方法只需要处理整数(对于序列来说);而 __getslice__() 方法 是专门用来处理切片的。当 __getslice__ 被弃用后,为了向后兼容和简化接口,使用 __getitem__ 来同时处理整数和 slice 对象就变得更简单了。

而且,除了序列以外,key 不一定非得是整数。自定义类可以支持任何类型的键。

撰写回答