Nested Function Change Variable In An Outside Function Not Working
Solution 1:
Python scoping rules 101:
a name bound in a function body is considered
local
unless explicitely declaredglobal
(Python 2.x and 3.x) ornonlocal
(Python 3.x only). This holds true whereever the assignment happens in the function's body. Trying to read a local variable before it's bound is of course an error.if a name is read but not bound in a function's body, it will be looked up in enclosing scopes (outer function(s) if any then global scope). NB: functions arguments are de facto local names so they will never be looked up in enclosing scopes.
Note that a += 1
is mainly a shortcut for a = a + 1
, so in your example a
is local (bound in the function's body and not explicitely declared global or nonlocal), but you try to read it (the rhs of a = a+1
) before it's bound.
In Python 3 you can solve this with a nonlocal
statement:
>>>defouter(a):...defchange():...nonlocal a... a += 1...print("before : {}".format(a))... change()...print ("after : {}".format(a))...>>>outer(42)
before : 42
after : 43
Python 2 doesn't have nonlocal
so the canonical hack is to wrap the variable in a mutable container (typically a list
but any mutable object would do):
>>>defouter(a):... _a = [a]...defchange():... _a[0] += 1...print("before : {}".format(_a[0]))... change()...print ("after : {}".format(_a[0]))...>>>outer(42)
before : 42
after : 43
which is quite ugly to say the least.
Now while closures are quite handy, they are mostly the functional counterpart of objects : a way to share state between a set of functions while preserving encapsulation of this state, so if you find you have a need for a nonlocal
variable perhaps a proper class might be a cleaner solution (though possibly not for your example that doesn't return the inner function but only uses it internally).
Solution 2:
i have two solutions for you:
#first one:# try with list, compound data types dict/listdefsome_func(a):
defchange_a():
a[0] += 1print(a[0])
change_a()
some_func([1])
>>> 2#second one#reference pointer from ctypes import *
defsome_func_ctypes(a):
defchange_a():
a[0] += 1print a.contents, a[0]
change_a()
i = c_int(1)
pi = pointer(i)
some_func_ctypes(pi)
>>> c_int(2) 2
Solution 3:
When you use the +=
operator, there is an assignment of a new value to a
. This turns a to a local in the eyes of the interpreter.
Post a Comment for "Nested Function Change Variable In An Outside Function Not Working"