我有以下代码段:
def isolation_level(level):
def decorator(fn):
def recur(level, *args, **kwargs):
if connection.inside_block:
if connection.isolation_level < level:
raise IsolationLevelError(connection)
else:
fn(*args, **kwargs)
else:
connection.enter_block()
try:
connection.set_isolation_level(level)
fn(*args, **kwargs)
connection.commit()
except IsolationLevelError, e:
connection.rollback()
recur(e.level, *args, **kwargs)
finally:
connection.leave_block()
def newfn(*args, **kwargs):
if level is None: # <<<< ERROR MESSAGE HERE, Unbound local variable `level`
if len(args):
if hasattr(args[0], 'isolation_level'):
level = args[0].isolation_level
elif kwargs.has_key('self'):
if hasattr(kwargs['self'], 'isolation_level'):
level = kwargs.pop('self', 1)
if connection.is_dirty():
connection.commit()
recur(level, *args, **kwargs)
return newfn
return decorator
它的作用并不重要,但我以原始形式发布,因为我无法用更简单的方式重新创建这种情况。
问题在于,当我致电isolation_level(1)(some_func)(some, args, here)
时,我在第21行(标有清单)中获得Unbound local variable
例外。我不明白为什么。我尝试重新创建相同的函数和函数调用结构,这些函数和函数调用不包含所有实现细节以找出错误。但是我没有收到异常消息。例如,以下工作:
def outer(x=None):
def outer2(y):
def inner(x, *args, **kwargs):
print x
print y
print args
print kwargs
def inner2(*args, **kwargs):
if x is None:
print "I'm confused"
inner(x, *args, **kwargs)
return inner2
return outer2
outer(1)(2)(3, z=4)
打印:
1
2
(3,)
{'z': 4}
我错过了什么?
修改
好的,问题是在第一个版本中我实际执行了对变量的赋值。 Python检测到这一点,因此假定变量是本地的。
答案 0 :(得分:9)
在编译时确定局部变量:变量level
的赋值在错误发生的行下面几行,使该变量在内部函数的本地变量。这一行
if level is None:
实际上尝试访问最里面范围内的变量level
,但是这样的变量还不存在。在Python 3.x中,您可以通过声明
nonlocal level
在内部函数的开头,如果你真的想要改变外部函数的变量。否则,您只需在内部函数中使用不同的变量名称。