I understand the concept of local and global variables in Python, but I just have a question about why the error comes out the way it is in the following code. Python execute the codes line by line, so it does not know that a is a local variable until it reads line 5. Does Python go back one line and tag it as an error after it tries to execute line 5?
a=0
def test():
print a #line 4, Error : local variable 'a' referenced before assignment
a=0 #line 5
test()
This is because, in python, you need to tell that you are going to modify the value of a global variable. You do that as:
With
global a
, you can modify variables in the function. You may want to have a look at this:Setup and Testing
To analyze your question, let's create two separate test functions that replicate your issue:
prints
0
. So, calling this function is not problematic, but on the next function:We get an error:
Disassembly
We can disassemble the two functions (first Python 2):
And we see that the first function automatically loads the global
a
, while the second function:seeing that
a
is assigned inside it, attempts to LOAD_FAST from the locals (as a matter of optimization, as functions are pre-compiled into byte-code before running.)If we run this in Python 3, we see nearly the same effect:
We see our error is on the LOAD_FAST again.
Short explanation:
a
variable is bound to thetest
function. When you attempt to print it, Python throws the error because the local variablea
will be initialized later. But if you remove thea=0
, the code will execute without any problems and output 0.Longer explanation
Python interpreter starts searching for the variable named
a
from the local scope. It sees thata
is indeed declared within the function and initialized only on the fifth line. Once it's found, the lookup is over.When it tries to process
print a
(forth line) it says 'Oh boy, I need to print a variable that's not initialized yet, I'd better throw an error.'Explanation based on function's bytecode
If you run this code:
you'll get this output:
Explanation on the unclear parts of the above:
a
's reference is being pushed onto the stack.a
So, the problem is that LOAD_FAST goes before STORE_FAST.
Python doesn't execute line by line in the function code you submitted. It has first to parse it as a bloc of execution. It decides if a variable is local or global depending if it is written at (function) local level. As it is the case, it decides that the variable is local, hence the error.