我创建了一个简单的装饰器,它接收一个参数(使用函数而不是类),当发生某些事情时:添加一行代码会中断前一行的执行。
代码如下:
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 设置为全局来解决该问题,但是全局变量通常是个坏主意。
