Skip to content Skip to sidebar Skip to footer

Nested Function Change Variable In An Outside Function Not Working

def some_func(a): def access_a(): print(a) access_a() outputs the value of a. However, if I want to change a in the nested function like this: def some_func(a):

Solution 1:

Python scoping rules 101:

  1. a name bound in a function body is considered local unless explicitely declared global (Python 2.x and 3.x) or nonlocal (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.

  2. 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"