Aar*_*ron 9 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 ...
Run Code Online (Sandbox Code Playgroud)
而在2.6:
class Super():
__metaclass__ = ABCMeta
@abstractmethod
def method(self):
pass
a = Super()
TypeError: Can't instantiate abstract class Super ...
Run Code Online (Sandbox Code Playgroud)
除了ABCMeta之外,如果我从对象派生Super,它们也都可以正常工作(我得到了预期的异常).
如果我从列表中派生超级,他们都"失败"(没有例外).
我想要一个抽象基类作为列表但是抽象,并且在子类中具体.
我做错了,还是我不想在python中使用它?
Ale*_*lli 15
使用Super
您的工作片段中的构建,您执行的操作Super()
是:
>>> Super.__init__
<slot wrapper '__init__' of 'object' objects>
Run Code Online (Sandbox Code Playgroud)
如果Super
继承list
,请调用它Superlist
:
>>> Superlist.__init__
<slot wrapper '__init__' of 'list' objects>
Run Code Online (Sandbox Code Playgroud)
现在,抽象基类可以用作mixin类,可以多次继承(获得ABC可能提供的"模板方法"设计模式功能)和一个具体的类,而不会产生由此产生的后代抽象.所以考虑:
>>> class Listsuper(Super, list): pass
...
>>> Listsuper.__init__
<slot wrapper '__init__' of 'list' objects>
Run Code Online (Sandbox Code Playgroud)
看到问题?通过多继承调用的规则Listsuper()
(由于存在悬空抽象方法而不允许失败)运行与调用相同的代码Superlist()
(您想要失败).在实践(list.__init__
)中,该代码并不反对悬挂抽象方法 - 只是object.__init__
这样做.并修复可能会破坏依赖于当前行为的代码.
建议的解决方法是:如果您需要抽象基类,则其所有基础必须是抽象的.因此,不要list
在你的基础中具体,使用作为基础collections.MutableSequence
,添加__init__
一个._list
属性,并MutableSequence
通过直接委托实现抽象方法self._list
.不完美,但也不是那么痛苦.