Python 2.6,3抽象基类
当我使用ABCMeta和abstractmethod时,我没有看到我所期望的 这在python3中效果很好:Python 2.6,3抽象基类,python,abstract-class,Python,Abstract Class,当我使用ABCMeta和abstractmethod时,我没有看到我所期望的 这在python3中效果很好: from abc import ABCMeta, abstractmethod class Super(metaclass=ABCMeta): @abstractmethod def method(self): pass a = Super() TypeError: Can't instantiate abstract class Super ...
from abc import ABCMeta, abstractmethod
class Super(metaclass=ABCMeta):
@abstractmethod
def method(self):
pass
a = Super()
TypeError: Can't instantiate abstract class Super ...
第2.6节:
class Super():
__metaclass__ = ABCMeta
@abstractmethod
def method(self):
pass
a = Super()
TypeError: Can't instantiate abstract class Super ...
除了ABCMeta之外,如果我从object派生Super,它们也可以很好地工作(我得到了预期的异常)
若我从列表中派生Super,它们都“失败”(并没有引发异常)
我想要一个抽象基类是一个列表,但它是抽象的,并且在子类中是具体的
我做错了吗,还是我不想在python中这样做?对于工作代码段中的
Super
构建,执行Super()
时调用的是:
>>> Super.__init__
<slot wrapper '__init__' of 'object' objects>
现在,抽象基类意味着可以作为mixin类使用,可以与一个具体的类一起被多重继承(以获得ABC可能提供的“模板方法”设计模式特性),而无需将生成的后代抽象。因此,请考虑:
>>> class Listsuper(Super, list): pass
...
>>> Listsuper.__init__
<slot wrapper '__init__' of 'list' objects>
>>类Listsuper(超级,列表):通过
...
>>>Listsuper.\uuu init__
看到问题了吗?根据多重继承的规则,调用Listsuper()
(不允许因为存在悬空的抽象方法而失败)与调用Superlist()
(您希望失败)运行相同的代码。在实践中(list.\uuuu init\uuu
),该代码不反对悬空的抽象方法,只反对对象。修复这个问题可能会破坏依赖于当前行为的代码
建议的解决方法是:如果您想要一个抽象基类,那么它的所有基类都必须是抽象的。因此,不要在你的基础中有具体的列表
,而是使用作为基础的集合.MutableSequence
,添加一个\uuuu init\uuuuu
属性,并通过直接委托给self来实现MutableSequence
的抽象方法。不完美,但也不是那么痛苦。事实上,问题在于\uuuuuu新的\uuuuuuu
,而不是\uuuuu初始的问题。例如:
from abc import ABCMeta, abstractmethod
from collections import OrderedDict
class Foo(metaclass=ABCMeta):
@abstractmethod
def foo(self):
return 42
class Empty:
def __init__(self):
pass
class C1(Empty, Foo): pass
class C2(OrderedDict, Foo): pass
C1()
失败,出现预期的TypeError
,而C2.foo()
返回42
>>> C1.__init__
<function Empty.__init__ at 0x7fa9a6c01400>
我想明确地说,这个问题与它无关。你到底想用这个来实现什么?一个具体的例子在这里会有很长的路要走。抽象基类是一个中毒的思想的愿望o_o musicfreak:我正在尝试实现一个基于列表的抽象基类,它为其派生类定义一个接口,而哪个基类不能被实例化。我希望能够使用派生类作为列表,因为这是我的对象的本质,因为我的对象更为特殊,所以需要额外的接口位。:)msw:为什么desiderata(“需要的东西是必要的”)是一个中毒的头脑?我猜你是说我不应该想要这个(用python),但为什么?什么是更具Python风格的机制?@msv,ABCs现在是Python 2.6及更高版本的一部分--deal.@Aaron,你没有做错什么,只是没有按照你的意愿工作--让我写一个答案来解释。@Aaron,我是在夸张,但除了我提到的SO链接中的一些模糊案例之外,还有som那些认为Python需要抽象类就像鱼需要自行车一样的人。在我看来,一个什么都不做的类不是一个类,而是一个接口定义。甚至在Python中包含ABC的理由也有点模棱两可:(我想我把我的评论搞糟了。)Alex,谢谢,这很清楚,切中要害。我现在有一些阅读要做。
>>> C1.__init__
<function Empty.__init__ at 0x7fa9a6c01400>
OrderedDict.bar = lambda self: 42