Firstly, it's related to this function:
a = 3
a = a+1
returns an error.
Isn't it when the local environment of
b couldn't find
'a', then it goes to the parent environment where
b is defined, that is, where
'a' is found to be
Why must I reference it with a
global a in order for it to work? Meaning, do I have to do this only when the immediate parent environment is the global environment? Because the below function seems to be able to reference the parent environment:
This is such a common issue that is is actually in the Python FAQ:
[...] when you make an assignment to a variable in a scope, that variable becomes local to that scope and shadows any similarly named variable in the outer scope. Since the last statement in foo assigns a new value to x, the compiler recognizes it as a local variable.
So, Python sees you're assigning to a local variable with
a = .. and thinks, hey, a local variable, I'm fine with this. But, when it actually bumps into the content of that assignment (
a + 1) and sees the same name
a it complains because you're trying to reference it before assigning it.
This is why the following doesn't raise an error:
def b(): a = 20 a = a + 2 return a
You first make an assignment,
a is treated as local to the function
b and when
a = a + 2 is encountered, Python knows
a is a local variable, no confusion is present here.
In the other case you added:
def b(): def c(): print c return c()
You are only referencing a name enclosed in the scope of function
b, referencing. If you changed this to a similar assignment as before, you'll get the same
def b(): def c(): c = c + 20 return c()
Because you are doing an assignment and the scope has to be clarified.
a = 3 def b(): a = a + 1 return a print(b())
Traceback (most recent call last): File "./tests/test1.py", line 12, in <module> print(b()) File "./tests/test1.py", line 9, in b a = a + 1 UnboundLocalError: local variable 'a' referenced before assignment
When you do the assignement
a = ... you have created always a local variable unless it has been declared
global which is not the case. Local resolution takes precedence.
Your example would obviously work with:
a = 3 def b(): global a a = a + 1 return a print(b())
But using globals, imho, should not be the way and hence passing
a as a parameter to function
b would be it:
a = 3 def b(a): a = a + 1 return a print(b(a))
Which agains produces the expected
Following the edition in the OP: you can always "reference" the global scope (and parent scope). But if you make assignments they take place in the local scope.
If your code (which is wronly indented and contains a new
c which isnt' anywhere) is meant to do this:
a = 3
def b(): def c(): print(a) return c() b()
It works ... and prints
3 because there is NO assignment and only referencing. As soon as you executing an assignment
a would again be created in the local scope.
Assignment will create a new variable in Python.
Here may help you.