我想装饰一个类方法,但无法弄清楚如何做到这一点。最小类示例:
class Circle(object):
def __init__(self,radius):
self.R = radius
def arc_length(self,theta):
return self.R*theta
现在让我说我想要另一种方法,它使arc_length始终相对于某个特定的弧长的其他值,所以我定义了一个函数如下:
def relative(rel_val):
def decorator(fn):
def wrapper(*args):
return fn(*args) - fn(rel_val)
return wrapper
return decorator
现在我将课程扩展到:
class Circle(object):
def __init__(self,radius):
self.R = radius
def arc_length(self,theta):
return self.R*theta
@relative(0.2)
def relative_arc_length(self,theta):
return self.arc_length(theta)
我希望这会产生预期的行为,但我得到错误: relative_arc_length()只需要2个参数(给定1个)
我认为这与self参数有关,但如果我在相对定义中将自我添加到fn(self,rel_val),它会给我:全局名称“self”未定义
那么我该如何解决这个问题呢?有趣的是,如果我做以下事情:
c = Circle(10)
relative(0.2)(c.arc_length)(1.5)
它按预期工作。
有人能指出我哪里出错了吗?此外,是否可以在类中定义装饰函数,如果是,我应该这样做吗?这是很好的编程习惯吗?
答案 0 :(得分:2)
return fn(*args) - fn(rel_val)
始终使用self
作为第一个参数调用方法。因此,在您的情况下,您将所有参数传递给第一个调用,但在第二个调用中忘记self
。
您必须从self
中提取args
并将其传递出去:
obj, value = args
return fn(obj, value) - fn(obj, rel_value)
您应该包含一个检查,以确保args
中任何时候只有两个值,因此您不会意外地使用装饰器来处理不兼容的方法。