实现 __getitem__ 方法

4

有没有一种方法可以实现__getitem__来支持整数和切片索引,而不需要手动检查参数的类型?

我看到了很多这种形式的示例,但是对我来说似乎非常hacky。

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))或类似的方法。


key 不一定是整数,因此试图将其强制转换为切片可能有点奇怪。 - Corley Brigman
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__ 被弃用时,为了向后兼容和更简单的 API,让 __getitem__ 处理整数和 slice 对象会更容易一些。

并且这忽略了一个事实,那就是在序列之外,key 不一定要是整数。自定义类可以自由地支持任何键类型。


啊哈,这是一种不错的 Pythonic 方法。与其测试一个对象的类型,不如测试它是否有特定的方法,这就是鸭子类型的本质。(虽然我认为我会使用 getattr 而不是捕获异常)显然,我有一个切片和索引的用例,否则我就不会问这个问题了... - rophl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接