访问类属性作为装饰器参数
Posted
技术标签:
【中文标题】访问类属性作为装饰器参数【英文标题】:Accessing class property as decorator argument 【发布时间】:2020-07-09 10:49:15 【问题描述】:我正在尝试应用conditional decorator,如另一篇 *** 帖子中所述,但我希望从正在使用的类内部设置条件。相反,我得到一个引用错误,指出 self 未定义。
class foo:
def __init__(self):
self.debug = True
@conditional_decorator(decorator, self.debug)
def function(self):
pass
我尝试定义一个全局变量并从 __init__() 方法内部对其进行更新,但它在作为装饰器的参数调用时保持其原始值。
debug = None
class foo:
def __init__(self):
self.debug = True
global debug
debug = self.debug
@conditional_decorator(decorator, debug)
def function(self):
pass
它起作用的唯一方法是声明一个全局变量并将其设置在类之外。
如何将类属性的值应用于装饰器?
【问题讨论】:
btwdecorators
在 python 读取程序文本时应用,而不是在运行时。
@quamrana:不,装饰器是在函数定义时应用的。
Python 函数定义是命令式的——执行一个会生成一个新的函数对象。在此之后立即应用装饰器。当 Python 读取源代码时,它们不会也不能应用;此时没有函数对象可以传递给装饰器,也可能没有装饰器可以调用。
@quamrana 当def
语句被执行时,在运行时。
class
语句也在运行时执行,这就是为什么类的主体不能引用类本身,因为该类还不存在而尸体正在被处决。
【参考方案1】:
装饰器不应该是有条件的。相反,当调用装饰函数时,它应该查看self.debug
以确定是使用原始函数还是包装部分。
def conditional_decorator(dec):
def decorator(func):
def _(self, *args, **kwargs):
f = func
if self.debug:
f = dec(f)
return f(self, *args, **kwargs)
return _
return decorator
def decorator(f):
def _(*args, **kwargs):
print("Decorated")
return f(*args, **kwargs)
return _
class foo:
def __init__(self, debug):
self.debug = debug
@conditional_decorator(decorator)
def function(self):
print("foo stuff")
foo(True).function()
print("===")
foo(False).function()
输出
Decorated
foo stuff
===
foo stuff
【讨论】:
【参考方案2】:@Maurice Meyer 给出的答案的更新,允许提名班级成员:
from functools import wraps
def conditional_decorator(decoration, member):
def decorator(method):
predecorated = decoration(method)
@wraps(method)
def wrapper(*args, **kwargs):
self = args[0]
condition = getattr(self, member)
if not condition:
return method(*args, **kwargs)
return predecorated(*args, **kwargs)
return wrapper
return decorator
#And used like this for example:
class foo:
def __init__(self, debug):
self.debug = debug
@conditional_decorator(decorator, "debug")
def function(self):
pass
f1 = foo(True)
f1.function()
【讨论】:
【参考方案3】:这是让装饰器处理类和参数的方式:
from functools import wraps
def conditional_decorator(param):
def real_decorator(fn):
@wraps(fn)
def wrapper(*args, **kw):
cls = args[0]
print(cls.debug)
print(param)
return wrapper
return real_decorator
class foo:
def __init__(self):
self.debug = True
@conditional_decorator('param1')
def function(self):
pass
f = foo()
f.function()
输出:
True
param1
【讨论】:
以上是关于访问类属性作为装饰器参数的主要内容,如果未能解决你的问题,请参考以下文章