如何在重写方法时保留父类方法的装饰器
解决子类重写方法自动复用父类装饰器的问题
这个问题我之前也碰到过——父类的方法带了装饰器,子类重写时总不想每次都手动加装饰器,也不想用super()来绕弯子。核心就是要让装饰器的逻辑能自动作用在子类的重写方法上,下面给你两个实用的方案:
方案一:模板方法模式(简单直观)
我们可以把父类带装饰器的method_a作为固定入口,子类只需要重写一个约定好的内部方法(比如_method_a),父类的method_a会自动调用这个内部方法,这样装饰器的逻辑就不会被子类覆盖了。
def decorator(method): def wrapper(self, *args, **kwargs): print("how are you ?") method(self, *args, **kwargs) return wrapper class A: @decorator def method_a(self, *args, **kwargs): # 固定调用子类重写的内部方法 self._method_a(*args, **kwargs) def _method_a(self, *args, **kwargs): # 父类默认实现 pass class B(A): def _method_a(self, *args, **kwargs): print("Fine thanks !") class_b = B() class_b.method_a()
运行这段代码就能得到你想要的输出:
how are you ? Fine thanks !
这个方案的好处是逻辑清晰,不需要理解复杂的元类知识,子类只需要按照约定重写_method_a就行,完全不用关心装饰器的存在。
方案二:元类自动添加装饰器(保持原有接口)
如果你希望子类还是能直接重写method_a,不用改方法名,那可以用元类来实现——元类能在类定义的阶段自动给指定方法加上装饰器。
def decorator(method): def wrapper(self, *args, **kwargs): print("how are you ?") method(self, *args, **kwargs) return wrapper class DecoratorMeta(type): def __new__(cls, name, bases, attrs): # 检查当前类是否定义了method_a,如果是就自动加装饰器 if 'method_a' in attrs: attrs['method_a'] = decorator(attrs['method_a']) return super().__new__(cls, name, bases, attrs) class A(metaclass=DecoratorMeta): @decorator def method_a(self, *args, **kwargs): pass class B(A): def method_a(self, *args, **kwargs): print("Fine thanks !") class_b = B() class_b.method_a()
这个方案里,子类的写法和你原来的完全一样,元类会在背后自动给method_a加上装饰器,完美满足“不用super()、不用重新定义装饰器”的要求。
内容的提问来源于stack exchange,提问作者Chjul
相关产品推荐
相关产品推荐

