Python中的抽象方法

24 投票
3 回答
23838 浏览
提问于 2025-04-16 16:48

我需要在Python(3.2)中实现类似于abstract protected的方法:

class Abstract:
    def use_concrete_implementation(self):
        print(self._concrete_method())

    def _concrete_method(self):
        raise NotImplementedError()


class Concrete(Abstract):
    def _concrete_method(self):
        return 2 * 3

定义一个“抽象”方法,仅仅是为了抛出一个NotImplementedError,这样做真的有用吗?

在其他语言中,protected的方法通常会用下划线开头,那么在Python中给抽象方法加个下划线算不算好习惯呢?

使用抽象基类(abc)会有什么好处吗?

3 个回答

0

基本上,在基类中一个空的方法在这里并不是必要的。你可以这样做:

class Abstract:
    def use_concrete_implementation(self):
        print(self._concrete_method())

class Concrete(Abstract):
    def _concrete_method(self):
        return 2 * 3

实际上,在Python中你通常甚至不需要基类。因为所有的调用都是动态解析的,如果这个方法存在,就会被调用;如果不存在,就会出现一个AttributeError错误。

注意:在文档中提到_concrete_method需要在子类中实现是很重要的。

10

当你不确定的时候,可以参考Guido的做法。

不要用下划线。只需将“抽象方法”定义为一行代码,并抛出NotImplementedError错误:

class Abstract():
    def ConcreteMethod(self):
        raise NotImplementedError("error message")
43

在Python中,通常会避免使用这种抽象方法。你可以通过文档来定义一个接口,然后简单地假设传入的对象符合这个接口,这种方式被称为“鸭子类型”。

如果你真的想定义一个带有抽象方法的抽象基类,可以使用abc模块来实现:

from abc import ABCMeta, abstractmethod

class Abstract(metaclass=ABCMeta):
    def use_concrete_implementation(self):
        print(self._concrete_method())

    @abstractmethod
    def _concrete_method(self):
        pass

class Concrete(Abstract):
    def _concrete_method(self):
        return 2 * 3

不过,这并不是Python的常规做法。abc模块的主要目的之一是引入一种机制来重载isinstance(),但通常情况下,我们会避免使用isinstance()检查,而更倾向于使用鸭子类型。如果你确实需要这样做,可以使用它,但不要把它当作定义接口的一般模式。

撰写回答