17

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

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

4

4 回答 4

18

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

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

例如,__getitem__collections.Sequence派生类中实现就足以为您的类提供__contains____iter__和其他方法。

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

于 2010-10-15T20:57:04.423 回答
15

子类化没有任何好处list这些方法都不会使用您覆盖的任何方法,因此您可能会遇到意外错误。此外,做一些事情self.append而不是self.foos.append或特别是self[4]而不是self.foos[4]访问您的数据经常会让人感到困惑。您可以制作与列表完全相同的东西,或者(更好)像您真正想要的列表一样,而只是子类化object

于 2010-10-15T23:02:18.557 回答
11

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

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

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

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

于 2010-10-15T20:39:26.790 回答
6

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

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

于 2010-10-15T20:50:16.903 回答