26. abc
abc 模块提供了在 Python 中定义抽象基类(abstract base classes)的组件。
26.1. 抽象基类
抽象基类可以通过从 ABC
派生来简单地创建,
1from abc import ABC
2
3class MyABC(ABC):
4 pass
也可以直接使用 ABCMeta
作为元类(metaclass)来定义抽象基类,
1from abc import ABCMeta
2
3class MyABC(metaclass=ABCMeta):
4 pass
26.2. 抽象方法
@abc.abstractmethod
是用于声明抽象方法的装饰器。
抽象方法与继承:
继承一个没有抽象方法的抽象类,不需要重写(override)抽象方法也能实例化。
继承有抽象方法的抽象类但没有重写抽象方法会报错,子类重写抽象方法不需要
abstractmethod
修饰。继承有抽象方法的非抽象类不会报错。
当 abstractmethod
与其他方法描述符配合使用时,它应当作为最内层的装饰器。
1class C(ABC):
2 @abstractmethod
3 def my_abstract_method(self):
4 pass
5 @classmethod
6 @abstractmethod
7 def my_abstract_classmethod(cls):
8 pass
9 @staticmethod
10 @abstractmethod
11 def my_abstract_staticmethod():
12 pass
13
14 @property
15 @abstractmethod
16 def my_abstract_property(self):
17 pass
18 @my_abstract_property.setter
19 @abstractmethod
20 def my_abstract_property(self, val):
21 pass
22
23 @abstractmethod
24 def _get_x(self):
25 ...
26 @abstractmethod
27 def _set_x(self, val):
28 ...
29 x = property(_get_x, _set_x)
26.3. 虚子类
register(subclass)
将子类注册为该抽象基类的虚子类(virtual subclass)。 issubclass
和 isinstance
等函数都能识别,但是该抽象基类不会出现在其 MRO(Method Resolution Order,方法解析顺序)中,虚子类并不会从抽象基类中继承任何方法,也无需重写抽象方法。虚子类是为类型检测准备的,由于不需要重写抽象方法,因此第三方接口的可扩展性和灵活性更高。
1from abc import ABC
2
3class MyABC(ABC):
4 pass
5
6MyABC.register(tuple)
7
8assert issubclass(tuple, MyABC)
9assert isinstance((), MyABC)
内建属性 __mro__
按顺序列出当前类及其祖先类, __subclasses__()
列出子孙类。
1from abc import *
2class A(metaclass=ABCMeta):
3 @abstractmethod
4 def func1(self):
5 pass
6
7@A.register
8class B:
9 def func2(self):
10 pass
11## 等价于 A.register(B)
12
13
14class C(A):
15 def func1(self):
16 pass
1>>> c = C()
2>>> print(C.__mro__)
3(<class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
4>>> print(A.__subclasses__())
5[<class '__main__.C'>]
26.4. 参考资料
abc — Abstract Base Classes
python之抽象类&abc模块+虚拟子类®ister
协议与接口与抽象基类