Given following code:
def A() :
b = 1
def B() :
# I can access 'b' from here.
print( b )
# But can i modify 'b' here? 'global' and assignment will not work.
B()
A()
For the code in B()
function variable b
is in outer scope, but not in global scope. Is it possible to modify b
variable from within B()
function? Surely I can read it from here and print()
, but how to modify it?
I'm a little new to Python, but I've read a bit about this. I believe the best you're going to get is similar to the Java work-around, which is to wrap your outer variable in a list.
Edit: I guess this was probably true before Python 3. Looks like
nonlocal
is your answer.I don't think you should want to do this. Functions that can alter things in their enclosing context are dangerous, as that context may be written without the knowledge of the function.
You could make it explicit, either by making B a public method and C a private method in a class (the best way probably); or by using a mutable type such as a list and passing it explicitly to C:
No you cannot, at least in this way.
Because the "set operation" will create a new name in the current scope, which covers the outer one.
Python 3.x has the
nonlocal
keyword. I think this does what you want, but I'm not sure if you are running python 2 or 3.For python 2, I usually just use a mutable object (like a list, or dict), and mutate the value instead of reassign.
example:
Outputs:
You can use an empty class to hold a temporary scope. It's like the mutable but a bit prettier.
This yields the following interactive output:
The short answer that will just work automagically
I created a python library for solving this specific problem. It is released under the unlisence so use it however you wish. You can install it with
pip install seapie
or check out the home page here https://github.com/hirsimaki-markus/SEAPIEuser@pc:home$ pip install seapie
outputs
the arguments have following meaning:
B()
, 1 means parentA()
and 2 would mean grandparent<module>
aka globalThe long answer
This is more complicated. Seapie works by editing the frames in call stack using CPython api. CPython is the de facto standard so most people don't have to worry about it.
The magic words you are probably most likely interesed in if you are reading this are the following:
The latter will force updates to pass into local scope. local scopes are however optimized differently than global scope so intoducing new objects has some problems when you try to call them directly if they are not initialized in any way. I will copy few ways to circumvent these problems from the github page
If you are feeling that using
exec()
is not something you want to go with you can emulate the behaviour by updating the the true local dictionary (not the one returned by locals()). I will copy an example from https://faster-cpython.readthedocs.io/mutable.htmlOutput: