变量作为装饰器参数

时间:2015-08-24 22:52:13

标签: python decorator

我发现装饰器参数是在装饰器定义中传递的,而不是像函数一样调用。

现在我想知道是否有可能让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()

2 个答案:

答案 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"