首先让我说我明白为什么子类list
不能像你期望的那样工作(因为list
是一个原始的内置类型,并且存在性能问题等等)。 AFAIK collections.UserList应该避免所有这些问题,并使子类化UserList完全像你期望的那样工作。例如,
class DumbList(list):
pass
d1 = DumbList([1,2,3])
d2 = DumbList([4,5])
type(d1 + d2)
返回<class 'list'>
,但
from collections import UserList
class DumbList(UserList):
pass
d1 = DumbList([1,2,3])
d2 = DumbList([4,5])
type(d1 + d2)
按预期返回<class '__main__.DumbList'>
。但是,即使使用UserList
代替list
,切片也会返回错误的类型:
class DumbList(UserList):
pass
d = DumbList([1,2,3])
type(d[:2])
按预期返回<class 'list'>
,而不是<class '__main__.DumbList'>
。
两个问题:
class DumbList(UserList):
def __getitem__(self, item):
result = UserList.__getitem__(self, item)
try:
return self.__class__(result)
except TypeError:
return result
......但似乎这种锅炉板代码应该是不必要的。
答案 0 :(得分:2)
在Python 2中,普通切片(没有步幅)将由__getslice__
method处理。 UserList
实现早于向语言添加扩展切片(使用步幅),并且从未添加对它们的支持,请参阅issue 491398。
Python 3实现只采用了Python 2版本,移至collections
并删除了__getslice__
和__setslice__
,因为Python 3不再支持这些版本。
因此,__getitem__
实施仍然只是:
def __getitem__(self, i): return self.data[i]
假设切片将在其他地方处理。
在Python 3中,通过将slice()
built-in type传递给__getitem__
来处理所有切片;只需测试该类型并将结果包装在type(self)
调用中:
def __getitem__(self, i):
res = self.data[i]
return type(self)(res) if isinstance(i, slice) else res