Python抽象基类(ABC)用于声明接口契约、约束子类行为,不提供默认逻辑;继承后必须实现所有@abstractmethod方法,否则实例化时抛TypeError,支持isinstance/isinstance运行时校验。

Python抽象基类(ABC)不是用来“实现功能”的,而是用来声明接口契约、约束子类行为的。它不提供默认逻辑,也不强制你写具体方法——但一旦你继承它,就必须满足它定义的接口要求,否则运行时报错。
抽象基类的核心作用:接口校验而非代码复用
和普通父类不同,ABC 的重点不在继承实现,而在类型检查与协议约定
-
@abstractmethod 标记的方法,子类必须重写,否则实例化时直接抛
TypeError - isinstance(obj, ABC) 和 issubclass(Cls, ABC) 可靠成立,用于运行时接口识别
- ABC 可以包含具体方法,但那只是辅助逻辑,不能替代抽象方法的强制实现
如何正确定义一个可校验的抽象接口
需显式继承 abc.ABC,并用 @abstractmethod 标记关键接口方法:
from abc import ABC, abstractmethodclass Drawable(ABC): @abstractmethod def draw(self) -> None: ...
@abstractmethod def bounding_box(self) -> tuple[int, int, int, int]: ...class Circle(Drawable): def draw(self) -> None: print("Drawing circle")
def bounding_box(self) -> tuple[int, int, int, int]: return (0, 0, 10, 10)✅ 实例化成功
c = Circle()
立即学习“Python免费学习笔记(深入)”;
❌ 若注释掉 bounding_box,实例化时会报错:
TypeError: Can't instantiate abstract class Circle
with abstract method bounding_box
运行时接口校验:判断对象是否“符合协议”
ABC 支持鸭子类型之上的显式契约验证,比 hasattr 更严谨:
-
isinstance(c, Drawable)→True(哪怕Circle没显式写class Circle(Drawable),也可通过Drawable.register(Circle)动态注册) - 适合在函数入口做参数类型断言:
def render(shape: Drawable): ... - 配合
typing.Protocol使用更灵活,但 Protocol 不参与运行时isinstance检查
常见误区与避坑提示
初学者容易把 ABC 当成“高级父类”来用,结果反而破坏设计意图:
- 不要只为复用几行代码而定义 ABC —— 那该用普通基类或组合
- 避免在 ABC 中塞太多抽象方法,接口越小越聚焦,越易实现和测试
-
__init__不应标记为@abstractmethod,构造逻辑通常由子类自行控制 - 若只需静态类型检查(如 mypy),可优先考虑
Protocol;若需运行时isinstance校验,才选 ABC










