我正在尝试为类方法(my_decorator
)定义一个python装饰器(f
),如下面的简化场景所示。 my_decorator
由param
进行参数化,这取决于类属性(在本例中为level
)。
class my_decorator:
def __init__(self, param):
self.param = param
def __call__(self, f):
def f_decorated(instance, c):
print("decorated with param = %d" % self.param)
return f(c)
return f_decorated
class A:
def __init__(self, level):
self.level = level
@my_decorator(param=self.level) # Here is the problematic line!
def f(x):
return x
if __name__ == "__main__":
a = A(level=2)
a.f(1) # name "self" is not defined
上面的代码不起作用,我得到一个“自我”没有定义错误。所以我的问题是,有没有办法实现上下文参数化装饰器的目标?
BTW,用例是:我试图实现持久的memoization技术(描述于 memoize to disk - python - persistent memoization) 缓存持续存在的文件取决于类A
,特别是“级别”。例如,我想保留文件cache_%d.txt % self.level
。
答案 0 :(得分:1)
陈,
装饰器在编译时或导入期间执行,因为在导入期间执行了类主体。因此,如果您在不创建该类实例的情况下执行您的代码段,也会抛出错误。
除了参数self.level在装饰器内部以外,对我来说没有多大意义,因为它是一个实例变量,所以你可以直接在函数f(x)中使用:
以下是一些更多细节:
答案 1 :(得分:1)
正如错误所述,self
此时并不存在。这应该是清楚的:self
仅作为方法的参数存在,并且您当时甚至不在方法中。装饰器与所有类级代码一样,在定义时进行评估。
我不完全确定您要实现的目标,但您可以使用字符串以及getattr
:
class my_decorator:
def __init__(self, param_name):
self.param_name = param_name
def __call__(self, f):
def f_decorated(instance, c):
param = getattr(instance, self.param_name)
print("decorated with param = %d" % param)
return f(c)
...
class A:
def __init__(self, level):
self.level = level
@my_decorator(param_name='level')
def f(x):
return x
答案 2 :(得分:1)
self
是一个变量。它只在方法内部定义,装饰器在外面。如果您需要装饰器内对象的属性,则可以通过string-name访问它:
class my_decorator:
def __init__(self, param):
self.param = param
def __call__(self, f):
def f_decorated(instance, c):
print("decorated with param = %d" % getattr(instance, self.param))
return f(instance, c)
return f_decorated
class A:
def __init__(self, level):
self.level = level
@my_decorator(param='level') # Here is the problematic line!
def f(self, x):
return x
if __name__ == "__main__":
a = A(level=2)
a.f(1) # name "self" is not defined