x = 4
def test():
print(x)
x = 2
test()
This gives an error because when you go to print(x)
, it sees that you have x
declared in the scope of the function test
, and it tells you you're trying to reference it without having declared it.
I know that if I do global x
it's no problem, or if I move the print statement...I know.
But I don't understand how the interpreter knows that I have x
redeclared after the print statement if it goes through the code one line at a time. How can it know what's coming?
There's clearly more to this than I'm aware of.
Who told you Python is executed one line at a time? Python is executed one bytecode at a time. And that bytecode comes from the compiler, which operates one statement at a time. Statements can be multiple lines. And a function definition is a statement.
So, one of the first steps in compiling a function definition is to gather up all of the variables assigned within that function's body. Any variable that's assigned, but doesn't have a global
or nonlocal
declaration, is a local.
(As a side note, that function body isn't actually compiled into a function, it's compiled into a code
object, which gets stashed somewhere, and only run when you call the function, and into some bytecode that builds a function
object out of that code
object, which gets run where your function definition occurs in the normal order.)
You can, in fact, see what the compiler made of your function by looking at its members:
>>> def foo():
... global y
... x=1
... y=1
>>> foo.__code__.co_varnames
('x',)
Then, when it's creating the bytecode for your function body, all variables in co_varnames
are compiled into local lookups, while the rest are compiled into global lookups:
>>> dis.dis(foo)
3 0 LOAD_CONST 1 (1)
3 STORE_FAST 0 (x)
4 6 LOAD_CONST 1 (1)
9 STORE_GLOBAL 0 (y)
12 LOAD_CONST 0 (None)
15 RETURN_VALUE
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With