如何装饰子类中的继承方法?
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:完全同意你的观点,你的方法看起来更好。但这不是我仍然想知道的。我想知道在示例中如何完成它是否是一种避免的方法,如果是,为什么。以上是关于如何装饰子类中的继承方法?的主要内容,如果未能解决你的问题,请参考以下文章