我想您是在问如何创建一个序列类型,一个可以用[]索引其实例的类型,就像一个列表。在

这样做的关键是实现一个或多个特殊方法,如文档中的Emulating container types所述。在

特别是,为my_obj[1]调用的特殊方法是^{}。在

对于一个非常简单的示例,让我们创建一个类似于所有小写英文字母的列表:class Letters:

def __getitem__(self, index):

return string.ascii_lowercase[index]

现在:

^{pr2}$

然而,这并不是一个完整的序列。例如:>>> len(letters)

TypeError: object of type 'Letters' has no len()

>>> reversed(letters)

TypeError: object of type 'Letters' has no len()

>>> isinstance(letters, collections.abc.Sequence)

False

如果您想实现一个完整的序列,^{}模块很有用,因为它提供的所有抽象基类也是mixin类,它们为您填充了大部分实现。例如,如果我们继承Sequence,我们只需定义__getitem__和{},它将免费为我们提供__contains__,__iter__,__reversed__,index,和{}的实现:class Letters(collections.abc.Sequence):

def __getitem__(self, index):

return string.ascii_lowercase[index]

def __len__(self):

return 26

现在,在list,tuple,和{}上工作的所有东西都在{}上工作:>>> letters = Letters()

>>> len(letters)

26

>>> reversed(letters)

>>> print(*reversed(letters))

z y x w v u t s r q p o n m l k j i h g f e d c b a

>>> letters.index('s')

10

>>> isinstance(letters, collections.abc.Sequence)

True

另外,我还做了一点欺骗,创建了一个序列,它只是委托给一个不同的序列(ascii_lowercase)来完成所有的工作。事实上,您通常可以这样做,但有时您做不到。当您做不到时,您通常需要自己处理负索引和切片,这看起来有点难看:def __getitem__(self, index):

if isinstance(index, slice):

return [self[i] for i in index.indices(len(self))]

if index < 0:

index += len(self)

return string.ascii_lowercase[index]

(您通常希望片段返回type(self)的另一个实例,不是一个列表,而是Letters的另一个实例,这没有任何意义,所以我只返回了一个列表。)

如果你想要一个可变的序列,比如一个列表而不是元组,在那里你可以修改值,或者添加和删除它们,还有一些方法要实现,但是没有什么大的不同。在

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐