请建议如何自定义Python切片

7 投票
1 回答
2438 浏览
提问于 2025-04-16 12:30

我有一个类,它是列表对象的子类。现在我需要处理切片操作。根据我在网上看到的资料,这个操作需要用到 __getitem__ 方法。至少在我使用的 Python 2.7+ 版本中是这样。我已经实现了这个方法(见下面的代码),但是当我传入一个切片时,__getitem__ 方法并没有被调用。相反,程序直接进行了切片操作,并返回了一个列表。我希望能返回我自己定义的 myList 的新实例。

请帮我找出问题出在哪里。

谢谢!

class myList(list):

    def __init__(self, items):

        super(myList, self).__init__(items)
        self.name = 'myList'


    def __getitem__(self, index):

        print("__getitem__")
        if isinstance(index, slice):
            print("slice")
            return self.__class__(
                self[x] for x in range(*index.indices(len(self)))
                )
        else: return super(myList, self).__getitem__(index)

if __name__ == "__main__":
    print("\nI'm tesing out custom slicing.\n")

    N = 10
    L = myList(range(N))

    L3 = L[3]
    L02 = L[:2]

1 个回答

17

请查看这个说明

object.__getslice__(self, i, j)

从2.0版本开始,这个功能被弃用了:支持切片对象作为__getitem__()方法的参数。(不过,CPython中的内置类型目前仍然实现了__getslice__()因此,当你在派生类中实现切片时,必须重写这个方法。

所以,因为你是从list这个类派生的,你必须重写__getslice__,即使它已经被弃用了。

我认为一般来说,应该尽量避免从内置类型派生,因为有太多奇怪的细节。如果你只是想要一个像列表一样工作的类,可以使用ABC来帮助你:

from collections import Sequence

class MyList(Sequence):
    def __init__(self, *items):
        self.data = list(items)

    def __len__(self):
        return len(self.data)

    def __getitem__(self, slice):
        return self.data[slice]

s = MyList(1,2,3)
# lots of free methods
print s[1:2], len(s), bool(s), s.count(3), s.index(2), iter(s)

撰写回答