如何实现强制Python子类重写方法时必须调用super()?
实现强制子类调用父类方法的装饰器
要实现类似@abstractmethod的效果,强制子类重写方法时必须调用父类的对应方法,可以自定义@must_call_super装饰器,通过标记状态的方式检查父类方法是否被执行。
完整实现代码
from functools import wraps def must_call_super(func): @wraps(func) def wrapper(self, *args, **kwargs): # 给实例添加临时标记,记录父类方法是否被调用 flag_name = f"_called_{func.__name__}" setattr(self, flag_name, False) # 执行父类原方法 result = func(self, *args, **kwargs) # 检查标记:若未被设为True,说明子类没调用父类方法 if not getattr(self, flag_name, False): raise RuntimeError(f"重写的方法 {func.__name__} 必须调用 super().{func.__name__}()") # 清理临时标记 delattr(self, flag_name) return result return wrapper class Foo: @must_call_super def i_do_things(self): print('父类方法被调用') # 标记父类方法已执行 flag_name = f"_called_{self.i_do_things.__name__}" setattr(self, flag_name, True) class Good(Foo): def i_do_things(self): super().i_do_things() print('子类方法也被调用') class Bad(Foo): def i_do_things(self): print('子类方法被调用,但未调用父类') # 正常执行 good = Good() good.i_do_things() # 调用方法时触发错误 bad = Bad() bad.i_do_things()
工作原理
- 装饰器
must_call_super会在父类方法执行前,给实例添加一个初始为False的临时标记。 - 父类方法内部会把这个标记设为
True,证明自身被执行过。 - 父类方法执行完毕后,装饰器检查标记状态:如果还是
False,说明子类重写方法时没有调用父类的super().xxx(),直接抛出运行时错误。 - 方法执行完成后删除临时标记,避免污染实例属性。
补充说明
- 这个实现是在方法调用阶段检查,而非类实例化阶段——因为实例化本身不涉及方法执行,只有调用重写后的方法时才会触发检查,这更符合实际使用逻辑。
- 如果需要在类定义时就做检查,可以借助元类实现,但会增加复杂度,且无法覆盖动态修改方法的场景。
内容的提问来源于stack exchange,提问作者Matt Billman
相关产品推荐
相关产品推荐

