Function - Unbound local variable problem in Python

De openkb
Aller à : Navigation, rechercher

Sommaire

Questions

I ve got a following code snippet:

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

It really doesn t matter what it does, however I post it in its original form, as I was unable to recreate the situation with anything simpler.

The problem is that when I call isolation_level(1)(some_func)(some, args, here) I get Unbound local variable exception in line 21 (marked on the listing). I don t understand why. I tried recreating the same structure of functions and function calls that wouldn t contain all the implementation details to figure out what is wrong. However I don t get the exception message then. For example the following works:

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)

Prints:

1
2
(3,)
{ z : 4}

What am I missing??

  EDIT   

Ok, so the problem is that in the first version I actually perform an assignment to the variable. Python detects that and therefore assumes the variable is local.

Answers

Local variables are determined at compile time: the assignments to the variable level a few lines below the line the error occurs in make that variable local to the inner function. So the line

if level is None:

actually tries to access a variable level in the innermost scope, but such a variable does not exist yet. In Python 3.x, you can solve this problem by declaring

nonlocal level

at the beginning of the inner function, if you actually want to alter the variable of the outer function. Otherwise, you can simply use a different variable name in the inner function.

Source

License : cc by-sa 3.0

http://stackoverflow.com/questions/5838034/unbound-local-variable-problem-in-python

Related

Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Outils