问题
def counter(x):
def _cnt():
#nonlocal x
x = x+1
print(x)
return x
return _cnt
a = counter(0)
print(a())
Above code gives the following error
UnboundLocalError: local variable 'x' referenced before assignment
Why this is not able to create a new object with value 'x+1' in the namespace of _cnt and bind it to x. we will have reference x in both function namespaces
回答1:
As soon as you assign to a name in a given scope, all references to the same name inside the same scope are local. Hence x + 1
cannot be evaluated (as it tries to reference the local x
).
Hence this works:
def f():
x = 42
def g():
print(x)
g()
f()
But this doesn't:
def f():
x = 42
def g():
print(x)
x = 42
g()
f()
The first print
has this bytecode:
0 LOAD_GLOBAL 0 (print)
3 LOAD_DEREF 0 (x)
6 CALL_FUNCTION 1
9 POP_TOP
while the second print
has this one:
0 LOAD_GLOBAL 0 (print)
3 LOAD_FAST 0 (x)
6 CALL_FUNCTION 1
9 POP_TOP
回答2:
The scopes of function counter
and _cnt
are not the same. Even though they're nested, it doesn't matter.
So the x
in counter
does not exist in _cnt
. Perhaps pass it as an argument (or use nonlocal
, as you seemed to have understood)
来源:https://stackoverflow.com/questions/19063648/python-closures