I just learned python @ decorator, it\'s cool, but soon I found my modified code coming out weird problems.
def with_wrapper(param1):
def dummy_wrapper(fn):
When Python parses a function, it notes whenever it finds a variable used on the left-hand side of an assignment, such as
param1 = 'new'
It assumes that all such variables are local to the function. So when you precede this assignment with
print param1
an error occurs because Python does not have a value for this local variable at the time the print statement is executed.
In Python3 you can fix this by declaring that param1
is nonlocal:
def with_wrapper(param1):
def dummy_wrapper(fn):
nonlocal param1
print param1
param1 = 'new'
fn(param1)
return dummy_wrapper
In Python2 you have to resort to a trick, such as passing param1 inside a list (or some other mutable object):
def with_wrapper(param1_list):
def dummy_wrapper(fn):
print param1_list[0]
param1_list[0] = 'new' # mutate the value inside the list
fn(param1_list[0])
return dummy_wrapper
def dummy():
@with_wrapper(['param1']) # <--- Note we pass a list here
def implementation(param2):
print param2
Handy for temporary situations or exploratory code (but otherwise not good practice):
If you're wanting to capture a variable from the outer scope in Python 2.x then using global is also an option (with the usual provisos).
While the following will throw (assignment of outer1 within inner makes it local and hence unbounded in the if condition):
def outer():
outer1 = 1
def inner():
if outer1 == 1:
outer1 = 2
print('attempted to accessed outer %d' % outer1)
This will not:
def outer():
global outer1
outer1 = 1
def inner():
global outer1
if outer1 == 1:
outer1 = 2
print('accessed outer %d' % outer1)
You assign param1
in the function, which makes param1
a local variable. However, it hasn't been assigned at the point you're printing it, so you get an error. Python doesn't fall back to looking for variables in outer scopes.