抽象基类
ABC 是一些不能被实例化的类。Java 或 C++ 语言的程序员应该对此概念十分熟悉。Python 3 添加了一个新的框架 —abc— 它提供了对 ABC 的支持。
这个 abc 模块具有一个元类(ABCMeta)和
修饰符(@abstractmethod 和 @abstractproperty)。如果一个
ABC 具有一个 @abstractmethod或 @abstractproperty,它就不能被实例化,但必须在一个子类内被覆盖。比如,如下代码:
>>>from abc import * >>>class C(metaclass = ABCMeta): pass >>>c = C()
这些代码是可以的,但是不能像下面这样编码:
>>>from abc import * >>>class C(metaclass = ABCMeta): ... @abstractmethod ... def absMethod(self): ... pass >>>c = C() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Can't instantiate abstract class C with abstract methods absMethod
更好的做法是使用如下代码:
>>>class B(C):
... def absMethod(self):
... print("Now a concrete method")
>>>b = B()
>>>b.absMethod()
Now a concrete method
ABCMeta 类覆盖属性 __instancecheck__ 和 __subclasscheck__,借此可以重载内置函数 isinstance() 和 issubclass()。要向
ABC 添加一个虚拟子类,可以使用 ABCMeta 提供的 register() 方法。如下所示的简单示例:
>>>class TestABC(metaclass=ABCMeta): pass >>>TestABC.register(list) >>>TestABC.__instancecheck__([]) True
它等同于使用 isinstance(list,
TestABC)。您可能已经注意到 Python 3 使用 __instancecheck__,而非 __issubclass__,使用__subclasscheck__,而非 __issubclass__,这看起来更为自然。若将参数 isinstance(subclass,
superclass) 反转成,比如superclass.__isinstance__(subclass),可能会引起混淆。可见,语法 superclass.__instancecheck__(subclass) 显然更好一点。
在 collections 模块内,可以使用几个
ABC 来测试一个类是否提供了特定的一个接口:
>>>from collections import Iterable >>>issubclass(list, Iterable) True
表 1 给出了这个集合框架的 ABC。
表 1. 这个集合框架的 ABC
| ABC | Inherits |
|---|---|
Container | |
Hashable | |
Iterable | |
Iterator |
Iterable |
Sized | |
Callable | |
Sequence |
Sized, Iterable, Container |
MutableSequence |
Sequence |
Set |
Sized, Iterable, Container |
MutableSet |
Set |
Mapping |
Sized, Iterable, Container |
MutableMapping |
Mapping |
MappingView |
Sized |
KeysView |
MappingView, Set |
ItemsView |
MappingView, Set |
ValuesView |
MappingView |
ABC 类型层次结构
Python 3 现支持能代表数值类的 ABC 的类型层次结构。这些 ABC 存在于 numbers 模块内并包括 Number、 Complex、Real、 Rational 和 Integral。图
1 显示了这个数值层次结构。可以使用它们来实现您自己的数值类型或其他数值 ABC。
图 1. 数值层次结构
新模块 fractions 可实现这个数值
ABC Rational。此模块提供对有理数算法的支持。若使用 dir(fractions.Fraction),就会注意到它具有一些属性,比如 imag、 real 和 __complex__。根据数值塔的原理分析,其原因在于 Rationals 继承自 Reals,而 Reals 继承自 Complex。
本文介绍了Python中的抽象基类(ABC),包括其定义、使用方法及如何通过@abstractmethod和@abstractproperty防止类被实例化。同时,文章还展示了如何利用ABCMeta元类重载isinstance()和issubclass()函数,并探讨了Python3中collections模块内的ABC,以及numbers模块中的数值类型层次结构。
1004

被折叠的 条评论
为什么被折叠?



