我发现装饰器参数是在装饰器定义中传递的,而不是像函数一样调用。
现在我想知道是否有可能让decorater像这样在运行时获取变量的值,decorater应该打印当前状态值而不是它定义的那个:
def deco(msg):
def decorater(func):
def wrapper(*args, **kwargs):
print msg
func(*args, **kwargs)
return wrapper
return decorater
def func():
local = {
"state": None
}
@deco(local["state"])
def test():
pass
def setState(newState):
local["state"] = newState
setState("start")
test()
setState("test")
test()
func()
答案 0 :(得分:2)
在您的示例中,deco()
是装饰者工厂;你正在创建装饰器,然后立即调用它。更一般地说,当您定义您正在装饰的功能时,调用装饰者。
您只需不要传递state
,并在wrapper()
内以全局形式访问它,就可以执行您尝试进行最少量更改的操作,在这种情况下,您不需要&#39 ; t需要deco()
;你可以直接使用@decorator
。也就是说,我认为有更好的方法可以做你想做的事情。
答案 1 :(得分:2)
约翰你应该阅读this。在python中,变量不是对象。您有疑问,是否“可以让装饰器在运行时获取变量的值”,因为python的范围规则没有意义。装饰器函数通常无法访问定义state
的范围。您可以通过多种方式获得所需的行为。
在不知道你想要做什么的具体细节的情况下,这里有两个可能有效。第一个使用闭包:
state = None
def with_closure(f):
def helper(*args, **kwargs):
# state is in scope for this function
print "Current state is: {}.".format(state)
return f(*args, **kwargs)
return helper
@with_closure
def foo():
return "something"
或者你可以制作一个跟踪状态的对象:
class StateHolder:
def set_state(self, state):
self.state = state
def with_state_object(state_object):
def decorator(f):
def helper(*args, **kwargs):
print "Current state is: {}.".format(state_object.state)
return f(*args, **kwargs)
return helper
return decorator
global_state = StateHolder()
global_state.set_state("some state")
@with_state_object(global_state)
def foo():
return "something"