python抽象类通过abc模块实现,核心是运行时检查、元类干预与特殊方法协议协同;@abstractmethod仅标记函数,abcmeta在类创建时收集未实现方法至__abstractmethods__,实例化时若其非空则抛出typeerror。

Python抽象类通过abc模块(Abstract Base Classes)实现,其核心不是靠语法强制,而是靠运行时检查 + 元类干预 + 特殊方法协议协同完成。关键不在“定义时报错”,而在“实例化时拦截”。
抽象方法如何被标记和识别
@abstractmethod装饰器本质是给函数对象动态添加一个__isabstractmethod__ = True属性。它不改变函数行为,只打上标记。Python在类创建阶段(即type.__new__之后、类对象返回前)会扫描所有属性,收集所有带该标记的可调用对象,存入类的__abstractmethods__集合中。
- 普通函数加
@abstractmethod→ 变成带__isabstractmethod__属性的函数对象 - 类中未实现的抽象方法 → 名字被加入
__abstractmethods__(如{'read', 'write'}) - 子类重写了全部抽象方法 →
__abstractmethods__自动变为空集
元类ABCMeta的关键作用
abc.ABCMeta是abc模块的元类,它接管了类的创建过程。当继承ABC或显式使用metaclass=ABCMeta时,该元类会在__new__中执行两项核心操作:
- 合并父类的
__abstractmethods__,并减去当前类中已实现的抽象方法名 - 若最终
__abstractmethods__非空,则将该类标记为“抽象类”,禁止直接实例化
注意:这个检查发生在类定义结束、类对象生成时,不是导入时,也不是调用时。
立即学习“Python免费学习笔记(深入)”;
实例化时的拦截机制
真正阻止创建实例的是ABCMeta.__call__(即类被调用时触发)。它在调用__new__和__init__前先检查:如果类的__abstractmethods__不为空,就抛出TypeError。这是用户看到“Can't instantiate abstract class…”错误的直接来源。
- 子类没实现所有抽象方法 →
__abstractmethods__ != set()→ 实例化失败 - 子类实现了全部 →
__abstractmethods__ == set()→ 正常走__new__流程 - 即使子类是抽象的(自己也加了
@abstractmethod),只要没被实例化,就不会报错
为什么register()不触发检查
ABC.register(ConcreteClass)是“虚拟子类”注册,它不修改ConcreteClass的MRO,也不触发ABCMeta的检查逻辑。它只是把ConcreteClass加入ABC._abc_registry,让issubclass(ConcreteClass, ABC)返回True。此时ConcreteClass仍可实例化,且ABC对其无约束力——因为它的__abstractmethods__根本没被检查过。
这种设计让abc保持轻量:协议检查只发生在“真继承”路径上,虚拟注册仅用于类型提示和isinstance判断。










