Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If Python is executed one line at a time, why can it see variables before they're declared?

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.

like image 737
temporary_user_name Avatar asked Dec 16 '22 05:12

temporary_user_name


1 Answers

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        
like image 196
abarnert Avatar answered May 02 '23 05:05

abarnert