如何在子类中装饰继承的方法?

19 投票
1 回答
11576 浏览
提问于 2025-04-18 13:28

我不太确定如何在继承的方法上使用装饰器。通常,装饰器是在定义之前加上的,但对于继承的函数,定义是在父类中,而不是子类中。我想避免在子类中重写这个方法的定义,而是简单地指定在继承的方法周围加上装饰器。

为了让我的意思更清楚,这里有一个我想表达的工作示例:

class Person():
    def __init__(self, age):
        self.age = age

    @classmethod
    def gets_drink(cls, ):
        print "it's time to get a drink!"
        return "A beer"

def dec(some_f):
    def legal_issue(obj,):
        some_f(obj)
        return 'A Coke'
    return legal_issue

class Child(Person):
    def __init__(self, age):
        Person.__init__(self, age=age)

    #in principle i'd like to write
    #@dec
    #self.gets_drink
    #which does not work
    #the only working way I found is by defining the method as a classmethod
    #and write this:

    @dec
    def gets_drink(self, ):
        return Person.gets_drink()

dad = Person(42)
son = Child(12)

print dad.gets_drink()
print son.gets_drink()

这个示例中的做法是有效的,但我觉得有点奇怪,因为它用一个调用原始方法的方式来替换这个方法,只是为了能加上装饰器。而且,为了让这个方法能正常工作,它需要在父类中被定义为类方法。

我是不是漏掉了什么?有经验的开发者会怎么做呢?

任何帮助、见解、批评意见和免费的咖啡都非常感谢!

相关问题:

1 个回答

20

你不一定要用装饰器的语法来使用装饰器。它其实就是一个可以调用的东西:

class Child(Person):
    def __init__(self, age):
        Person.__init__(self, age=age)

    gets_drink = dec(Person.gets_drink.__func__)

这个做法会把装饰器的返回值添加到子类中,作为一个同名的方法。__func__属性可以把绑定的(类)方法解包,拿到原始的函数。

需要注意的是,你的新方法现在是一个普通的方法,而不是类方法。如果你想让它成为类方法,就得把结果重新用classmethod()包裹起来。

这个做法之所以有效,是因为下面的语法:

@decorator_expression
def function_definition():
    pass

其实只是一些语法上的简化,等同于:

def function_definition():
    pass
function_definition = decorator_expression(function_definition)

撰写回答