我有一个类,本质上是一个事物的集合/列表。但我想在这个列表中添加一些额外的函数。我想要的是:
li = MyFancyList()
。变量li
在用作列表时应该表现为列表:[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
。但这是推荐的Python疗法吗?如果是,应该考虑什么?如果没有,还有什么更好的方法?
如果您不想重新定义
list
的每个方法,我建议您使用以下方法:这将使诸如
append
、extend
等方法可以开箱即用。但是,请注意,在这种情况下,神奇的方法(例如__len__
,__getitem__
等)将不起作用,因此您至少应该像这样重新声明它们:请注意,在这种情况下,如果要重写
list
(extend
,例如)的方法,可以声明自己的方法,这样调用就不会通过__getattr__
方法。例如:这里最简单的解决方案是从
list
类继承:然后可以使用
MyFancyList
类型作为列表,并使用其特定方法。继承在对象和
list
之间引入了强耦合。您实现的方法基本上是一个代理对象。 使用的方式取决于使用对象的方式。如果它必须是一个列表,那么继承可能是一个不错的选择。EDIT:正如@acdr所指出的,为了返回
MyFancyList
而不是list
,一些返回列表副本的方法应该被重写。实现这一点的简单方法是:
如果您只需要列表行为的一部分,请使用composition(即您的实例包含对实际列表的引用),并仅实现您所需的行为所必需的方法。这些方法应将工作委托给实际列表类的任何实例都包含对的引用,例如:
单独实现
__getitem__
将提供大量特性,例如迭代和切片。如果希望列表的完整行为,请从^{} 继承。
UserList
是列表数据类型的完整Python实现。那么为什么不直接从
list
继承呢?直接从
list
(或用C编写的任何其他内置代码)继承的一个主要问题是,内置代码可能调用,也可能不调用在用户定义的类中重写的特殊方法。以下是pypy docs的相关摘录:另一段引自卢西亚诺·拉马略的Fluent Python,第351页:
。。。更多内容,第370页以上:
在玩了一会儿之后,
list
内置的问题似乎就不那么重要了(我试图在Python 3.4中打破它一段时间,但是没有发现一个非常明显的意外行为),但是我仍然想发布一个原则上可以发生什么的演示,下面是一个带有adict
和aUserDict
的:如您所见,来自
dict
的__init__
方法忽略了重写的__setitem__
方法,而来自UserDict
的__init__
方法则没有。相关问题 更多 >
编程相关推荐