我有一个类,它本质上是一个事物的集合/列表。但我想在此列表中添加一些额外的功能。我想要的是以下内容:
- 我有一个实例
li = MyFancyList()
。 Variableli
should behave as it was a list whenever I use it as a list:[e for e in li]
,li.expand(...)
,for e in li
. - 另外它应该有一些特殊的功能,比如
li.fancyPrint()
,li.getAMetric()
,li.getName()
。
我目前使用以下方法:
class MyFancyList:
def __iter__(self):
return self.li
def fancyFunc(self):
# do something fancy
这可以用作像 [e for e in li]
这样的迭代器,但我没有像 li.expand(...)
这样的完整列表行为。
第一个猜测是将 list
继承到 MyFancyList
。但这是推荐的 pythonic 方式吗?如果是,需要考虑什么?如果不是,什么是更好的方法?
原文由 Michael 发布,翻译遵循 CC BY-SA 4.0 许可协议
如果您只想要列表行为的一部分,请使用组合(即您的实例持有对实际列表的引用)并仅实现您想要的行为所必需的方法。这些方法应该将工作委托给您的类的任何实例引用的实际列表,例如:
单独实施
__getitem__
将为您提供数量惊人的功能,例如迭代和切片。如果您想要列表的 完整 行为,请继承自
collections.UserList
。UserList
是列表数据类型的完整 Python 实现。那么为什么不直接继承
list
呢?直接从
list
(或任何其他用 C 编写的内置函数)继承的一个主要问题是,内置函数的代码可能调用也可能不调用用户定义的类中覆盖的特殊方法。这是 pypy 文档 的相关摘录:另一句话,来自 Luciano Ramalho 的 Fluent Python ,第 351 页:
…等等,第 370 页以上:
玩了一会儿之后,内置的
list
的问题似乎不那么严重(我试图在 Python 3.4 中打破它一段时间但没有发现真正明显的意外行为),但我仍然想要发布原则上可能发生的事情的演示,所以这里有一个dict
和UserDict
:As you can see, the
__init__
method fromdict
ignored the__setitem__
method, while the__init__
method from ourUserDict
没有。