Python的abc模块通过TypeError阻止未实现抽象方法的类被实例化,需同时继承ABC并用@abstractmethod标记方法;仅继承ABC或仅用装饰器均无效,且抽象方法签名必须完全一致。

Python 的 abc 模块不能真正“强制”运行时检查,但能通过抛出 TypeError 阻止未实现抽象方法的类被实例化——这是最实用、最可控的接口约束方式。
定义抽象基类时必须显式继承 ABC 并用 @abstractmethod
只加 @abstractmethod 不继承 ABC 是无效的;反过来,只继承 ABC 但没标记抽象方法,该类就只是普通基类,不构成接口约束。
常见错误:写成 class MyInterface:(没继承 ABC),或漏掉 @abstractmethod 装饰器,结果子类不实现也能实例化。
正确写法:
from abc import ABC, abstractmethod
<p>class Drawable(ABC):
@abstractmethod
def draw(self) -> None:
pass</p><pre class="brush:php;toolbar:false;">@abstractmethod
def bounds(self) -> tuple[int, int, int, int]:
pass
-
ABC是元类,负责在类定义结束时扫描所有@abstractmethod标记的方法 - 抽象方法体可以是
pass、...或任意占位实现,运行时不执行 - 抽象方法支持类型提示,但
abc本身不校验类型,那是mypy的事
子类未实现全部抽象方法会导致 TypeError 实例化失败
这个报错发生在 MySubclass() 这一刻,不是导入时、也不是继承时——所以它不影响模块加载,也允许你先写骨架再补实现。
典型错误现象:TypeError: Can't instantiate abstract class Shape with abstract method draw
注意点:
- 只要有一个抽象方法没实现,就会报错,哪怕其他都实现了
- 方法名、参数签名(包括默认值)必须完全一致;仅改类型提示不算实现
- 如果子类里写了同名方法但忘了
self参数,会因签名不匹配而仍被判定为未实现
想绕过强制检查?可以用 __abstractmethods__ = set()(慎用)
这不是推荐做法,但在测试或动态构造类时偶尔需要临时解除约束。直接修改类的 __abstractmethods__ 属性可清空抽象方法集合。
示例:
class StubDrawable(Drawable):
pass
<h1>手动清空抽象方法集合(绕过检查)</h1><p>StubDrawable.<strong>abstractmethods</strong> = set()</p><h1>现在可以实例化了</h1><p>obj = StubDrawable() # 不报错
</p>
- 这种操作破坏了接口契约,只应在单元测试 mock 或调试中临时使用
- 一旦设置了
__abstractmethods__ = set(),后续即使补上方法也不会自动恢复约束 - 更安全的替代方案是用
unittest.mock.Mock或定义一个带空实现的测试基类
真正容易被忽略的是:抽象基类无法约束属性访问、下标操作或魔术方法以外的调用行为;比如你声明了 draw,但子类把 draw 写成类属性而非方法,abc 也检测不到——它只认可调用签名匹配的实例方法。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











