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.
The UnboundLocalError: local variable referenced before assignment error is raised when you try to assign a value to a local variable before it has been declared. You can solve this error by ensuring that a local variable is declared before you assign it a value.
A symbol that has not been given a value by assignment or in a function call is said to be “unbound.”
Normally, when you create a variable inside a function, that variable is local, and can only be used inside that function. To create a global variable inside a function, you can use the global keyword.
The nonlocal keyword is used to work with variables inside nested functions, where the variable should not belong to the inner function. Use the keyword nonlocal to declare that the variable is not local.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With