如何让Python子类方法自动调用父类方法实现?
让子类方法自动前置调用父类实现的几种方案
问题背景
现有代码如下:
class Base: def method(self): print("Base method called") class Derived(Base): def method(self): print("Derived method called")
需求是:让子类的method方法自动且强制在执行自身逻辑前调用父类的method实现,执行Derived().method()时期望输出:
Base method called Derived method called
同时要避免在子类方法内部显式编写super().method()这类调用。
此前尝试过__init_subclass__的实现方式,但存在Pylance报错、逻辑不够直观的问题:
class Base: def __init_sublcass__(cls, *args, **kwargs): # 原代码存在拼写错误:init_sublcass → init_subclass def wrapper(self): super().method() self.method() cls.method = wrapper def method(self): print("Base method called")
方案一:装饰器封装父类调用逻辑
在父类定义专用装饰器,子类方法通过装饰器标记,即可自动前置调用父类方法,逻辑清晰且兼容IDE检查:
class Base: @classmethod def enforce_parent_call(cls, func): def wrapper(self, *args, **kwargs): # 调用父类的method实现 super(type(self), self).method(*args, **kwargs) # 执行子类自身方法逻辑 return func(self, *args, **kwargs) return wrapper def method(self): print("Base method called") class Derived(Base): @Base.enforce_parent_call def method(self): print("Derived method called")
方案二:元类实现强制统一调用
如果需要强制所有子类自动调用父类方法(无需子类手动加装饰器),可以用元类实现全局规则:
class EnforceParentCallMeta(type): def __new__(cls, name, bases, attrs): # 仅当子类重写了method时才包装 if 'method' in attrs: original_method = attrs['method'] def wrapped_method(self, *args, **kwargs): # 遍历父类找到method并调用 for base in bases: if hasattr(base, 'method'): base.method(self, *args, **kwargs) break return original_method(self, *args, **kwargs) attrs['method'] = wrapped_method return super().__new__(cls, name, bases, attrs) class Base(metaclass=EnforceParentCallMeta): def method(self): print("Base method called") class Derived(Base): def method(self): print("Derived method called")
方案三:改进__init_subclass__实现
修正原方案的拼写错误,优化逻辑并补充方法元信息,解决Pylance报错问题:
class Base: def __init_subclass__(cls, *args, **kwargs): super().__init_subclass__(*args, **kwargs) # 仅在子类重写method时执行包装 if cls.method is not Base.method: original_method = cls.method def wrapper(self, *args, **kwargs): super(cls, self).method(*args, **kwargs) return original_method(self, *args, **kwargs) # 复制原方法的元信息,避免IDE报错 wrapper.__name__ = original_method.__name__ wrapper.__doc__ = original_method.__doc__ cls.method = wrapper def method(self): print("Base method called") class Derived(Base): def method(self): print("Derived method called")
内容的提问来源于stack exchange,提问作者Tommy
相关产品推荐
相关产品推荐

