繁体   English   中英

Python装饰器变量得分

[英]Python decorator variable score

我创建了一个简单的装饰器,该装饰器在发生某些事情时会收到一个参数(使用函数而不是类):添加一行代码会中断上一行的执行。

这是代码:

def my_decorator(sublabel):
    def duration_wrapper(f):

        print sublabel
        # Uncommenting this code will break the previous line - why?
        # if sublabel is None:
        #     sublabel = f.func_name

        def wrapped_function(*args, **kwargs):
            return f(*args, **kwargs)

        return wrapped_function

    return duration_wrapper

@my_decorator('me')
def myf(): pass

myf()

取消注释这些代码行会导致此异常:

Traceback (most recent call last):
  File "test.py", line 16, in <module>
    @my_decorator('me')
  File "test.py", line 4, in duration_wrapper
    print sublabel
UnboundLocalError: local variable 'sublabel' referenced before assignment

谁能解释为什么不注释这两行代码会破坏它吗?

装饰器是闭包,并且从封闭范围引用的封闭范围中的所有标签必须在封闭范围内保持静态。 如果要使封闭范围中的变量可从封闭范围中可变,则需要将其包装在可变对象中,例如:

def my_decorator(sublabel):
    sublabel = [sublabel]
    def duration_wrapper(f):

        print sublabel[0]
        if sublabel[0] is None:
            sublabel[0] = f.func_name

        def wrapped_function(*args, **kwargs):
            return f(*args, **kwargs)

        return wrapped_function

    return duration_wrapper

就像@Bakuriu在评论中指出的那样,Python 3引入了nonlocal来消除此限制,并且您也可以将sublabel为global来解决该问题,但通常情况下,globals是一个坏主意。

您的问题可以简化为这个简单的例子

sublevel = 1

def func():
    print sublevel
    sublevel = 2

func()

问题是,当您在内部范围中分配变量时,您将屏蔽外部范围(全局级别或父函数级别范围),请阅读文档以了解python范围规则是如何工作的,要注意的重要一点是scopes are determined statically

因此,在我的示例中,您需要在调用print之前说出global sublevel ,而您的案例则需要使用nonlocal关键字(python 3+)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM