On Python 3, use the nonlocal keyword:
The
nonlocalstatement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope excluding globals. This is important because the default behavior for binding is to search the local namespace first. The statement allows encapsulated code to rebind variables outside of the local scope besides the global (module) scope.
def foo():
a = 1
def bar():
nonlocal a
a = 2
bar()
print(a) # Output: 2
On Python 2, use a mutable object (like a list, or dict) and mutate the value instead of reassigning a variable:
def foo():
a = []
def bar():
a.append(1)
bar()
bar()
print a
foo()
Outputs:
[1, 1]
Answer from Adam Wagner on Stack OverflowOn Python 3, use the nonlocal keyword:
The
nonlocalstatement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope excluding globals. This is important because the default behavior for binding is to search the local namespace first. The statement allows encapsulated code to rebind variables outside of the local scope besides the global (module) scope.
def foo():
a = 1
def bar():
nonlocal a
a = 2
bar()
print(a) # Output: 2
On Python 2, use a mutable object (like a list, or dict) and mutate the value instead of reassigning a variable:
def foo():
a = []
def bar():
a.append(1)
bar()
bar()
print a
foo()
Outputs:
[1, 1]
You can use an empty class to hold a temporary scope. It's like the mutable but a bit prettier.
def outer_fn():
class FnScope:
b = 5
c = 6
def inner_fn():
FnScope.b += 1
FnScope.c += FnScope.b
inner_fn()
inner_fn()
inner_fn()
This yields the following interactive output:
>>> outer_fn()
8 27
>>> fs = FnScope()
NameError: name 'FnScope' is not defined
Take this function as an example:
def foo(self, param1):
count = 0
buffer = []
def inner(x):
buffer.append(x + param1)
count += 1
inner(5)
So, the inner function can freely access param1 and buffer. However, it will complain about count, and in order to make it work, you need to declare "nonlocal count".
I was wondering why is this the case, how is the stack organized such that param1 and buffer is accessible without the need to declare nonlocal, but for count, it needs a nonlocal declaration? I'm guessing it has something to do with it being a primitive... but then again, so is param1
How to change outer function local variables from an inner function in Python? - Stack Overflow
Nested function has an issue with a variable
Modify the function variables from inner function in python - Stack Overflow
scopes in nested functions
In Python 3.x this is possible:
def f1():
x = 5
def f2():
nonlocal x
x+=1
return f2
The problem and a solution to it, for Python 2.x as well, are given in this post. Additionally, please read PEP 3104 for more information on this subject.
def f1():
x = { 'value': 5 }
def f2():
x['value'] += 1
Workaround is to use a mutable object and update members of that object. Name binding is tricky in Python, sometimes.
Is there a command like global or nonlocal with which I can make x=10 in my_nested_nested_function?
With global x it gets 1, with nonlocal it gets 100. If i comment the line where I set x to 100 in my_nested_function then the print statement puts out 10 (Which would be a workaround). But is there a way if I had to use the variable in my_nested_function?
x = 1
def my_function():
x = 10
def my_nested_function():
x = 100
def my_nested_nested_function():
nonlocal x
print(x)
my_nested_nested_function()
my_nested_function()
my_function()
In Python 3.x, you can use the nonlocal keyword:
def outer():
string = ""
def inner():
nonlocal string
string = "String was changed by a nested function!"
inner()
return string
In Python 2.x, you could use a list with a single element and overwrite that single element:
def outer():
string = [""]
def inner():
string[0] = "String was changed by a nested function!"
inner()
return string[0]
You can also get around this by using function attributes:
def outer():
def inner():
inner.string = "String was changed by a nested function!"
inner.string = ""
inner()
return inner.string
Clarification: this works in both python 2.x and 3.x.
def generic_function(x, y):
x += 1 y += 1
x = 1
y = 2
generic_function(x, y)
print(x, y)
Above the variables x and y do not change because generic_function creates local variables x and y.
But I learned I could do that this way:
def generic_function():
list\[0\] += 1 list\[1\] += 1
list = [1, 2]
generic_function()
print(list[0], list[1])
A list can be used as parameters to the function, so the generic_function will modify the list that the name list refers to. And so no unwanted local variables are created.
But it seems strange to make your program search in a list for a value so many times, is there any other way to do it? Why couldn't I change which value the name x refers to directly?
You could simply reference the 'theVariable' inside the nested InnerFunction, if you don't want to pass it's value as a parameter:
def OuterFunction():
# Declare the variable
theVariable = 42
def InnerFunction():
# Just reference the 'theVariable', using it, manipulating it, etc...
print(theVariable)
# Call the InnerFunction inside the OuterFunction
InnerFunction()
# Call the OuterFunction on Main
OuterFunction()
# It will print '42' as result
You can just reference the variable directly, as follows;
def outer():
x = 1
def inner():
print(x + 2)
inner()
outer()
Prints: 3
First off, in this simple case you could return the desired value from inner() and assign it when calling inner(). But let's assume that this is a simplified example, and that you are in fact changing multiple variables, or returning inner somewhere else where it will be called multiple times and need to reexamine its variable.
In Python 3 you can declare variab as nonlocal, which would allow you to change it. In Python 2, the only way is to switch to mutating an object with state freshly created on each call to outer. For example, using a list:
def outer():
variab = [""]
#some code including, presumably, a call to inner()
def inner():
# some code
variab[0] = "new_value"
print variab[0]
Nicer variants of this can be achieved, e.g. by making variab contain a dict or a Python instance with mutable __dict__. An elegant idiom is to use the __dict__ of the inner function itself as the container:
def outer():
def inner():
# some code
inner.variab = "new_value"
inner.variab = ""
#some code including, presumably, a call to inner()
print inner.variab
The cleanest way to do this is explicitly:
def outer():
variab = ""
#some code
def inner(variab):
# some code
variab = "new_value"
return variab
variab = inner(variab)
print variab
Now you don't have to worry about scoping, can test inner in isolation, etc. It is clear to the reader that inner requires access to variab to do its thing, and that variab may be different after the call.
See PEP-0020: "Explicit is better than implicit"; and "Readability counts".