How would one decorate an inherited method in the child class?

Deadly 提交于 2020-01-22 14:11:35

问题


I'm not quite sure how to use a decorator on an inherited method. Normally decorators are put before the definition but for an inherited function the definition is given in the parent and not the child class. I would like to avoid rewriting the definition of the method in the child class and simply specify to put the decorator around the inherited method.

To make myself clearer, here is a working example of what I mean:

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

The way it is done in this example works, but it looks somehow weird to me, replacing the method with a call to the original method only to be able to put the decorator. Also, for this to work, the method needs to be defined as a classmethod in the parent class.

Am I missing something? How would experienced developers do this?

Any help, insights, critical comments and free coffees are much appreciated!


回答1:


You don't have to use a decorator in decorator syntax. It is just a callable:

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

    gets_drink = dec(Person.gets_drink.__func__)

This adds the return value of the decorator to the child class as a method with the same name. The __func__ attribute unwraps the bound (class) method, retrieving the original function.

Note that your new method is now a regular method, not a classmethod, you'd have to re-wrap the result in a classmethod() call for that.

This works because the syntax

@decorator_expression
def function_definition():
    pass

is just syntactic sugar for:

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


来源:https://stackoverflow.com/questions/24768400/how-would-one-decorate-an-inherited-method-in-the-child-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!