Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 2.6,3抽象基类_Python_Abstract Class - Fatal编程技术网

Python 2.6,3抽象基类

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 ...

当我使用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 ...
第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