0

Running this code prints 2.

x = 2
def foo():
    print(x)
foo()

However, running this code returns an UnboundLocalVariable exception when I attempt to print x. (Line 3).

x = 2
def foo():
    print(x)
    x = 10
foo()

Python is an interpreted language, so I don't understand how it can 'know' that I will assign x a value as a local variable on line 5, when it gives an error on line 4. Is there some sort of pseudo-compiling when I define the function?

amdson
  • 1
  • `def` is a executable statement, so the interpreter gets a chance to see all the statements in the body of the function being define during that process. – martineau Jul 06 '21 at 00:42
  • Although Python *interprets* your code line-by-line, it *reads* it well in advance. While it can't know what the environment will look like in the future, the entire file has been read into memory long before the first line gets executed. – Silvio Mayolo Jul 06 '21 at 00:42
  • 1
    *languages* are not interpreted. That is a category error. Language *implementations are*. CPython compiles source code to byte code which is executed by the runtime byte code interpreter. Much like Java. So this is decide by the CPython *compiler*. The rule is simple, any assignment within a function renders that variable *local* – juanpa.arrivillaga Jul 06 '21 at 01:05
  • There are very few purely interpreted language implementations in use today. One example, I believe, is bash – juanpa.arrivillaga Jul 06 '21 at 01:08
  • Python is not any more an "interpreted" language than Java or C#. – Karl Knechtel Sep 09 '22 at 09:35

1 Answers1

0

In python, variable definition is attached to the scope that it's in. In this example, x is attached to the scope of foo at the time foo is compiled. Python gives you an UnboundLocalError on line 3 because x is attached to foo's scope but has not been bound yet. The same error can be seen if no global x is present:

>>> def foo():
...     print(x)
...     x = 10
...
>>> foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in foo
UnboundLocalError: local variable 'x' referenced before assignment

Exploring further, we can see that when compiling line-by-line (outside of a function, in the interactive REPL), python can't look ahead to see if x will be defined:

>>> print(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined

And we get a NameError instead. UnboundLocalError is a subclass of NameError because it indicates the same problem, just with a more helpful name and message.

VintiumDust
  • 95
  • 1
  • 6