python无虚函数,可用notimplementederror模拟抽象行为:基类方法中显式抛出该异常,强制子类重写,运行时调用即报错;可单独使用,亦可配合abc.abc和@abstractmethod增强语义。

Python里没有虚函数,但可以用NotImplementedError模拟抽象行为
Python本身不支持C++那种编译期检查的纯虚函数,但通过在基类方法中主动抛出NotImplementedError,能实现运行时强制子类重写的效果。这不是语法层面的约束,而是约定+报错驱动的设计模式——只要子类忘了重写,一调用就立刻崩,比静默返回None或默认值更容易暴露问题。
关键点在于:这个异常必须在基类方法体中显式抛出,不能只靠文档说明;且最好配合abc.ABC和@abstractmethod一起用(后者提供更严格的抽象类语义),但单用NotImplementedError已足够轻量、兼容老版本Python。
什么时候该用NotImplementedError而不是@abstractmethod
当你的基类不需要被标记为“不可实例化”,或者项目还在用Python abc模块虽存在,但部分特性受限),又或者你只想对个别方法做重写提示而非整个类走抽象流程时,直接抛NotImplementedError更灵活。
常见场景包括:
- 框架插件基类中留出钩子方法(如
on_start()、transform_input()),不希望用户漏实现但又不想强制继承ABC - 快速原型开发中临时加个“待实现”占位,避免后续调用时逻辑空转
- 已有类结构不便改造成
ABC,但需要逐步增强约束力
NotImplementedError的典型写法和易错点
错误示范是只写pass或return None,这会让子类误以为方法可选;正确做法是在方法体内第一行就抛异常,并附带清晰提示。
示例:
class Processor:
def process(self, data):
raise NotImplementedError("子类必须实现 process() 方法")
class JsonProcessor(Processor):
def process(self, data):
return {"parsed": True, "data": data}
容易踩的坑:
- 把
raise NotImplementedError写在方法签名后但没缩进,导致语法错误 - 在
__init__里抛异常——这会阻止所有实例化,而你想限制的是方法调用 - 异常信息写成“请实现”,太模糊;应明确指出哪个方法、为什么必须重写
- 在父类方法里做了部分实现再抛异常,逻辑割裂,建议全交给子类
和@abstractmethod混用时要注意什么
可以共存,但没必要重复抛异常:@abstractmethod已隐含运行时检查,再手动抛NotImplementedError属于冗余。如果你用了@abstractmethod,子类未实现对应方法时,连实例化都会失败,错误信息是TypeError: Can't instantiate abstract class ... with abstract method xxx。
所以实际选择是:
- 要严格禁止基类实例化 + 统一抽象语义 → 用
abc.ABC+@abstractmethod - 只要求方法被重写,允许基类实例化(比如做默认兜底)→ 单用
NotImplementedError - 基类本身不能实例化,但某些方法允许有默认实现 → 混合使用:
@abstractmethod标核心方法,其他方法用NotImplementedError或提供默认逻辑
最常被忽略的是:即便用了@abstractmethod,子类里仍可能意外覆盖了父类已实现的方法,导致本该复用的逻辑丢失——这时候NotImplementedError反而更直白地提醒“这里你得自己写”。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











