3

I don't understand the error in this example. Shouldn't print(b) print 6, by the Python LEGB rule? When the interpreter scans f(a) function in line 2, does it memorize that b = 33 and puts in the memory heap or just remembers the information that b is a local variable?

b = 6
def f(a):
    print(a)
    print(b)
    b = 33
f(20)
# UnboundLocalError: local variable 'b' referenced before assignment
Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253
Marko Savic
  • 69
  • 1
  • 3

1 Answers1

3

When Python scans your functions it sees an assignment to b. This assignment creates specific bytecode (LOAD FAST) that instructs Python to load the name b as a local variable.

You can see this if you disassemble the bytecode (using the dis module) created for the function f:

from dis import dis
dis(f)
  2           0 LOAD_GLOBAL              0 (print)
              2 LOAD_FAST                0 (a)
              4 CALL_FUNCTION            1
              6 POP_TOP

  3           8 LOAD_GLOBAL              0 (print)
             10 LOAD_FAST                1 (b)
             12 CALL_FUNCTION            1
             14 POP_TOP

the relevant instruction here is:

LOAD_FAST                1 (b)

which loads the name b as a local variable.

When print(b) is encountered, it tries to load the name b but b hasn't been defined yet (the assignment has not been performed): you referenced it (print(b)) before an assignment to it has been made.

Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253
  • The dis module shows what's going on. Does it work by reading the whole body of the function, and then after that prints the bytecode on the screen, or does it print after each line scan? – Marko Savic Sep 21 '17 at 02:20
  • Everything `dis` needs to create what you see is located in `f.__code__`, it doesn't read anything, it uses what already exists @MarkoSavic – Dimitris Fasarakis Hilliard Sep 21 '17 at 02:30