Take a sample program:
c = 10
def myfunc():
print(c)
myfunc()
This prints 10 as expected, but if we look at another program:
c = 10
def myfunc():
print(c)
c = 1
myfunc()
It says: local variable 'c' referenced before assignment
Here, if the python interpreter is actually going line by line, shouldn't it print 10
before reaching the next line to conclude there's a local variable?
Python has a lexer, tokenizer and parser. Does it go through all the code, parse it before executing them line by line?
Is that why it's able to say there's a local variable down the function?
Before the interpreter takes over, Python performs three other steps: lexing, parsing, and compiling. Together, these steps transform the source code from lines of text into byte code containing instructions that the interpreter can understand. The interpreter's job is to take these code objects and follow the instructions.
So the error is produced by Python when it is translating the source code into byte code. During this step, scope is also decided. This is because the byte code will need to reference the correct variable locations. However, in this case, it is now wired to reference a variable that is not defined in the scope, causing the error at runtime.
In this snippet of code there are no syntax errors, no scope errors.
c = 10
def myfunc():
print(c)
myfunc()
In this program, the c = 1
implicitly makes the variable local. However, this is defined after the print(c)
which is not yet defined in its scope.
c = 10
def myfunc():
print(c)
c = 1
myfunc()
So if you did this:
c = 10
def myfunc():
c = 1
print(c)
myfunc()
or
c = 10
def myfunc():
global c # Changes the scope of the variable to make it accessible to the function
print(c)
c = 1
myfunc()
the code would work just fine.
To answer your question:
Does it go through all the code, parse it before executing them line by line?
Yes, it does.