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

Posted

技术标签:

【中文标题】如何装饰子类中的继承方法?【英文标题】:How would one decorate an inherited method in the child class? 【发布时间】:2014-09-06 06:00:48 【问题描述】:

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

为了让自己更清楚,这里是我的意思的一个工作示例:

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()

在这个例子中它的工作方式是可行的,但在我看来有点奇怪,将方法替换为对原始方法的调用只是为了能够放置装饰器。此外,要使其工作,该方法需要在父类中定义为类方法。

我错过了什么吗?有经验的开发人员如何做到这一点?

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

【问题讨论】:

我没有关注你。你为什么把gets_drink换成原来的电话? 您的意思是您想知道使用装饰器是否比使用super() 调用原始方法更好? @MartijnPieters:最初我想修改子类对象的一些参数,据我所知,这可以通过装饰器轻松完成。 我没有真正看到它;您可以轻松地为新的覆盖方法赋予不同的签名。您不必必须使用与父类的重写方法相同的参数。 @MartijnPieters:是的,我知道。而且我很清楚,如果我只是覆盖该方法,那么上面的这个虚拟示例会看起来更好。但问题是一个更普遍的问题,装饰器很有用,假设对于父类我们的方法不需要装饰器,但对于子类它需要。在这种情况下,我会寻找一个看起来像示例的解决方案。你会采取不同的方式吗? 【参考方案1】:

你没有在装饰器语法中使用装饰器。它只是一个可调用的:

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)

【讨论】:

酷,感谢您的回答!好吧,在示例中,该方法被定义为类方法只是为了使其工作 - 它不需要是类方法。事实上,如果gets_drink 不是类方法,那么__func__ 也应该不需要。 @jojo:在 Python 2 中,您仍然希望使用 __func__,因为返回了未绑定的方法对象。展开避免了对父类和分层添加不必要的引用。在 Python 3 中,访问类上的函数只返回函数。 但我仍然想知道,我在示例中的做法是不是不好? @jojo:如果你想将装饰器应用到子类中的继承方法,我做的是更好的方法。 @MarijnPieters:完全同意你的观点,你的方法看起来更好。但这不是我仍然想知道的。我想知道在示例中如何完成它是否是一种避免的方法,如果是,为什么。

以上是关于如何装饰子类中的继承方法?的主要内容,如果未能解决你的问题,请参考以下文章

Python子类方法从超类方法继承装饰器

如何在不复制整个方法的情况下将装饰器添加到 Python 中的继承方法?

对于装饰器模式的理解

对于装饰器模式的理解

对于装饰器模式的理解

重写的方法是不是继承python中的装饰器?