在列入子列表之前要考虑什么?

时间:2010-10-15 20:37:00

标签: python list subclassing

我最近正在处理我遇到的编码问题,有人看着代码说子类列表很糟糕(我的问题与该类无关)。他说你不应该这样做,而且它带来了一堆不好的副作用。这是真的吗?

我在询问列表是否通常对子类不好,如果是,那么原因是什么。或者,在Python中对列表进行子类化之前我应该​​考虑什么?

4 个答案:

答案 0 :(得分:17)

abstract base classes模块中提供的collections,尤其是MutableSequence,在实现类似列表的类时非常有用。这些在Python 2.6及更高版本中可用。

使用ABCs,您可以实现类的“核心”功能,它将提供逻辑上取决于您定义的内容的方法。

例如,在__getitem__派生类中实施collections.Sequence就足以为您的班级提供__contains____iter__和其他方法。

您可能仍希望使用包含的列表对象来完成繁重的工作。

答案 1 :(得分:17)

继承list没有任何好处。这些方法都不会使用您覆盖的任何方法,因此您可能会遇到意外错误。此外,执行self.append而不是self.foos.append或特别是self[4]而不是self.foos[4]来访问您的数据时,常常会感到困惑。你可以创建一些像一样或(更好)的东西,但是就像你真正想要的列表而只是继承object

答案 2 :(得分:11)

我认为我问自己的第一个问题是,“我的新对象真的是一个列表吗?”。它像列表一样走路,像列表那样说话吗?或者是别的什么?

如果它是一个列表,那么所有标准列表方法都应该有意义。

如果标准列表方法没有意义,那么您的对象应该包含一个列表,而不是列表。

在旧的python(2.2?)中,由于各种技术原因,子类别列表是一个坏主意,但在现代的python中它很好。

答案 3 :(得分:6)

尼克是对的。 此外,虽然我不能说Python,但在其他OO语言(Java,Smalltalk)中,对列表进行子类化是一个坏主意。一般应该避免继承,而是使用委托组合。

相反,您创建一个容器类并将调用委托给列表。容器类具有对列表的引用,您甚至可以在自己的方法中公开列表的调用和返回。 这增加了灵活性,允许您稍后更改实现(不同的列表类型或数据结构),而不会破坏任何代码。如果您希望列表执行不同的listy类型的事情,那么您的容器可以执行此操作并使用普通列表作为简单的数据结构。 想象一下,如果你有47种不同的列表用途。你真的想要维护47个不同的子类吗? 相反,你可以通过容器和接口来做到这一点。一个类维护并允许人们通过接口调用新的和改进的方法,并且实现仍然隐藏。