Python中的未绑定局部变量问题

jul*_*icz 5 python bug-tracking exception function local-variables

我有一个以下代码片段:

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
Run Code Online (Sandbox Code Playgroud)

它的作用并不重要,但是我将它以原始形式发布,因为我无法用更简单的方式重新创建这种情况.

问题是,当我打电话时,我在第21行isolation_level(1)(some_func)(some, args, here)得到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)
Run Code Online (Sandbox Code Playgroud)

打印:

1
2
(3,)
{'z': 4}
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

编辑

好吧,问题是在第一个版本中我实际执行了对变量的赋值.Python检测到它,因此假定变量是本地的.

Sve*_*ach 9

局部变量在编译时确定:变量的赋值level在错误发生的行下面几行,使得该变量在内部函数的本地变量.所以行

if level is None:
Run Code Online (Sandbox Code Playgroud)

实际上尝试访问level最里面范围内的变量,但是这样的变量还不存在.在Python 3.x中,您可以通过声明来解决此问题

nonlocal level
Run Code Online (Sandbox Code Playgroud)

在内部函数的开头,如果你真的想要改变外部函数的变量.否则,您可以在内部函数中使用不同的变量名称.