关于oop:Python中的抽象方法

Abstract methods in Python

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

1
2
3
4
5
6
7
8
9
10
11
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,这实际上有用吗?

在抽象方法中使用下划线(在其他语言中是EDOCX1[1])是否很好?

抽象基类(abc)会改进什么吗?


在Python中,通常避免将这些抽象方法组合在一起。您通过文档定义一个接口,并简单地假设传入的对象实现该接口("duck-typing")。

如果您真的想用抽象方法定义一个抽象基类,可以使用abc模块:

1
2
3
4
5
6
7
8
9
10
11
12
13
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()检查以支持duck类型。如果需要,可以使用它,但不能作为定义接口的一般模式。


当有疑问时,要像吉多那样做。

没有下划线。只需将"abstract method"定义为引发notimplementederror的一行程序:

1
2
3
class Abstract():
    def ConcreteMethod(self):
        raise NotImplementedError("error message")


基本上,这里不需要基类中的空方法。就这样做:

1
2
3
4
5
6
7
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需要在子类中实现。