是否可以创建抽象类?

新手上路,请多包涵

如何在 Python 中抽象类或方法?

我尝试重新定义 __new__() 像这样:

 class F:
    def __new__(cls):
        raise Exception("Unable to create an instance of abstract class %s" %cls)

但现在如果我创建一个继承自 F G 这样:

 class G(F):
    pass

那么我也无法实例化 G ,因为它调用其超类的 __new__ 方法。

有没有更好的方法来定义抽象类?

原文由 user1632861 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 570
2 个回答

使用 abc 模块创建抽象类。根据您的 Python 版本,使用 abstractmethod 装饰器声明方法抽象,并使用三种方式之一声明类抽象。

在 Python 3.4 及更高版本中,您可以继承自 ABC 。在早期版本的 Python 中,您需要将类的元类指定为 ABCMeta 。指定元类在 Python 3 和 Python 2 中有不同的语法。三种可能性如下所示:

 # Python 3.4+
from abc import ABC, abstractmethod
class Abstract(ABC):
    @abstractmethod
    def foo(self):
        pass

 # Python 3.0+
from abc import ABCMeta, abstractmethod
class Abstract(metaclass=ABCMeta):
    @abstractmethod
    def foo(self):
        pass

 # Python 2
from abc import ABCMeta, abstractmethod
class Abstract:
    __metaclass__ = ABCMeta

    @abstractmethod
    def foo(self):
        pass

无论您使用哪种方式,您都无法实例化具有抽象方法的抽象类,但能够实例化提供这些方法具体定义的子类:

 >>> Abstract()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Abstract with abstract methods foo
>>> class StillAbstract(Abstract):
...     pass
...
>>> StillAbstract()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class StillAbstract with abstract methods foo
>>> class Concrete(Abstract):
...     def foo(self):
...         print('Hello, World')
...
>>> Concrete()
<__main__.Concrete object at 0x7fc935d28898>

原文由 alexvassel 发布,翻译遵循 CC BY-SA 3.0 许可协议

执行此操作的老派( PEP 3119 之前)方法只是在调用抽象方法时在抽象类中调用 raise NotImplementedError

 class Abstract(object):
    def foo(self):
        raise NotImplementedError('subclasses must override foo()!')

class Derived(Abstract):
    def foo(self):
        print 'Hooray!'

>>> d = Derived()
>>> d.foo()
Hooray!
>>> a = Abstract()
>>> a.foo()
Traceback (most recent call last): [...]

这不具有与使用 abc 模块相同的好属性。您仍然可以实例化抽象基类本身,并且在运行时调用抽象方法之前不会发现您的错误。

但是,如果您正在处理一小组简单的类,可能只使用一些抽象方法,则这种方法比尝试浏览 abc 文档要容易一些。

原文由 Tim Gilbert 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题