Python's LEGB rule

How Python resolves variables according to scopes.

2017-07-11

Newcomers to Python are sometimes surprised that variables declared "while indented" can be available "outside of the indentation", for example in the following code.

with open('filename.ext', 'r') as f:
    first_line = f.readline()

print(first_line) # this works

To resolve name-to-object mappings, Python follows the LEGB (Local, Enclosing, Global, Built-in) rule, and this is the same for Python 2 and 3.

What this means is that it first searches in the local namespace (inside a function/method), then enclosed namespace (enclosing functions, e.g. function inside function, including lambdas), global namespace (module namespace), and finally the built-in namespace. If Python can't resolve a name within any of the namespaces (i.e. the final built-in namespace check fails), Python will raise a NameError.

If you assign to a variable within a function, the variable will be declared locally to the function (thus part of the function namespace), so for example running the following code will get you the error UnboundLocalError: local variable 'var' referenced before assignment.

def func():
    print(var)
    var = 'local'

var = 'global'
func()

Python 3 allows you to override default name resolution rules with the global and nonlocal keywords. We can make the above code do what we wanted it to do by stating global var to make var resolve to the global variable before the local assignment.

def func():
    global var
    print(var) # prints 'global'
    var = 'local'
    print(var) # prints 'local'

var = 'global'
func()

You can use nonlocal in pretty much the same way for nested functions.

def outer():
    def inner():
        nonlocal var
        var = 'nonlocal'
    var = 'local'
    print(var) # prints 'local'
    inner()
    print(var) # prints 'nonlocal'

outer()

Another neat thing is Python allows forward references.