如何在不出现类型问题的情况下子类化Python列表?

44 投票
4 回答
38525 浏览
提问于 2025-04-17 06:34

我想在Python中实现一个自定义的列表类,让它继承自list。为了让这个自定义列表能够完全兼容所有列表操作,我需要重写基类list中的哪些方法呢?

这个问题提到至少需要重写__getslice__方法。经过进一步的研究,我发现还需要重写__add____mul__。所以我写了这段代码:

class CustomList(list):
    def __getslice__(self,i,j):
        return CustomList(list.__getslice__(self, i, j))
    def __add__(self,other):
        return CustomList(list.__add__(self,other))
    def __mul__(self,other):
        return CustomList(list.__mul__(self,other))

以下这些语句可以正常工作,即使没有重写的方法:

l = CustomList((1,2,3))
l.append(4)                       
l[0] = -1
l[0:2] = CustomList((10,11))    # type(l) is CustomList

这些语句只有在上面类定义中重写了方法后才能正常工作:

l3 = l + CustomList((4,5,6))    # type(l3) is CustomList
l4 = 3*l                        # type(l4) is CustomList
l5 = l[0:2]                     # type(l5) is CustomList

我唯一不知道怎么做的是让扩展切片返回正确的类型:

l6 = l[0:2:2]                   # type(l6) is list

我需要在我的类定义中添加什么,才能让l6的类型变成CustomList呢?

另外,除了扩展切片,还有其他列表操作会返回list类型而不是CustomList吗?

4 个回答

8

一个可能的解决办法是:创建一个UserList的子类,而不是直接使用list。这个方法对我有效。UserList就是为了这个目的而存在的。

27

你可能需要看看文档中的这两个部分:

补充:为了处理扩展切片,你需要让你的 __getitem__ 方法能够处理切片对象(具体可以参考这里,往下看一点)。

30

首先,我建议你参考一下Björn Pollex的建议(赞一个)。

要解决这个特定的问题(type(l2 + l3) == CustomList),你需要实现一个自定义的__add__()方法:

   def __add__(self, rhs):
        return CustomList(list.__add__(self, rhs))

还有关于扩展切片的内容:

    def __getitem__(self, item):
        result = list.__getitem__(self, item)
        try:
            return CustomList(result)
        except TypeError:
            return result

我还建议你...

pydoc list

...在你的命令提示符下运行。你会看到list类提供了哪些方法,这会给你一个很好的提示,告诉你需要重写哪些方法。

撰写回答