Trusted answers to developer questions

The LEGB rule in Python

Get Started With Data Science

Learn the fundamentals of Data Science with this free course. Future-proof your career by adding Data Science skills to your toolkit — or prepare to land a job in AI, Machine Learning, or Data Analysis.

When we use a variable name, how does Python know where to find its value? It uses the LEGB rule!

LEGB stands for Local, Enclosing, Global, Built-in. These are the possible scopes of a variable in Python. We also use these words to describe namespaces, which store variable names and values and are how Python determines scope.

The order Local, Enclosing, Global, Built-in is the order of precedence for scope resolution. That means Python searches for the value of a name in each of these namespaces in turn.

Namespaces

In Python and other languages, variables and are stored in namespaces. A namespace maps names to objects. The namespace that contains a variable determines when that variable is in scope, that is, when it can be used.

Namespaces are how Python keeps track of variables.

In a namespace, an object name maps to the object itself. Namespaces keep track of all objects, not just user-defined variables. For example, functions are also objects in Python. A namespace can contain function names that map to the contents of those functions.

Namespaces are created and destroyed as a program runs. The following code snippet will create a namespace that contains a variable with name x and value 3. After the program finishes running, this namespace is deleted.

x = 3

Namespaces are often represented with diagrams. The namespace is drawn as a big box containing variable names (words) with arrows pointing to objects (boxes). Inside each box is a value(s). An arrow from a variable name to a box indicates that the name maps to the object that the box represents.

The code snippet above could be represented in a diagram like this:

widget



Namespaces can also be nested. Calling a function creates a new namespace:

def f(x):
return x
y = f(3)

Here are the namespaces that exist and the objects they contain as this snippet runs. Notice that function parameters are stored in that function’s namespace when it is created (i.e., when the function is called).

Line 1
1 of 4

The LEGB Rule

Now, let’s return to the LEGB rule. Each letter stands for a different scope.

  • The local scope is the scope of all objects in the current namespace.

  • The enclosing scope is the scope of any objects in the namespace that encloses the current namespace, which may or may not exist. In the example below, the namespace of f encloses the namespace of g, so the name x is in the enclosing scope at line 3.

def f(x):
def g(y):
return y
g(x)
  • The global scope is the scope of objects in the module-level namespace. Creating a variable outside of a function or class will put it in the global namespace.

  • The built-in scope is the scope of all objects that are built into the Python language. Reserved names like dict are found in this namespace.

When searching for an object by name, Python first searches the local namespace. If the name is not present in the local namespace, Python searches any enclosing namespaces, starting from the innermost enclosing namespace. Once there are no more enclosing namespaces to search, Python searches the global namespace. If the object name is not defined in any of the preceding namespaces, Python searches the built-in namespace. Finally, if Python cannot find a variable with the requested name in any namespace, it will raise a NameError exception.

So, Python searches from the inside out. The takeaway is that namespaces are isolated. Creating, deleting, or changing the value of an object in one namespace will not affect objects with the same name in other namespaces.

Let’s look at some examples. Try to predict the output of the following code snippets.

Example 1

x = 5
def f(x):
print(f'The value of x is {x}')
f(3)

Explanation

This snippet will define variable x in the global namespace with value 5 and a function f that takes one parameter and prints out a string followed by the value of its parameter. When f is called, its parameter x is initialized in the function’s local namespace with value 3. On line 4, Python searches for x first in the local namespace, finds a name x that maps to an integer with value 3, and stops its searching there, at the innermost namespace, and prints “The value of x is”, followed by the value of the x that it found, “3.”

Example 2

dict = 5
def f(dict):
print(f'The value of x is {dict}')
f(3)

Explanation

This is exactly the same as the previous code snippet except that the name dict is already defined in the built-in namespace. However, we can redefine variables in outer namespaces, so this snippet will create a variable dict in the global namespace with value 5 and a variable dict in the local namespace with value 3. On line 4, Python again searches from the inside out and first finds the value of dict inside of the local namespace.

Although this is working code, it is not good practice to redefine built-in variables! It is easy to forget that you have called a variable dict when you are trying to create a dictionary later in a program. This can lead to confusing errors!

Example 3

x = 5
def f(y):
def g(z):
print(f'The value of x is {x}')
g(y)
f(3)

Explanation

On line 1, we define variable x in the global namespace with value 5. On line 3, we define function f in the global namespace. On line 8, we call f. This creates a local namespace (inside of the global namespace) that contains function g and parameter y with value 3. On line 6, we call g, creating a new local namespace that contains parameter z with value 3. The previous local namespace, created by calling f, becomes an enclosing namespace.

Finally, we reach the print statement! Now, Python searches the existing namespaces for an object named x. There is no such variable in the local namespace, so Python tries the enclosing namespace. There is no x defined there either, so Python searches the global namespace. There, we find a name x that maps to an object with value 5. So, Python ouputs “The value of x is,” followed by the value of the x in the global namespace, “5.”


Example 4

Just one more example! We will only change the first line.

y = 5
def f(y):
def g(z):
print(f'The value of x is {x}')
g(y)
f(3)

In this snippet, x is not defined in any namespace. At line 5, Python will search the namespaces in order from local to enclosing to global to built-in, and none of them will have a variable with the name x. So, Python will raise a NameError exception.

Accessing variables in other namespaces

Namespace Dictionaries

We can obtain a dictionary of all current global objects by calling the globals() function. Similarly, we can obtain a dictionary of local objects by calling locals().

Scope keywords

Suppose you are working inside a function with variable x defined, but you want to change the value of the variable x defined at the module level. The LEGB rule tells us that x will resolve to the object in the local namespace.

x = 5
def f():
# This new value of `x` will persist only
# while the namespace of f still exists
x = 3
print(f'Before: the value of x is {x}')
f()
print(f'After: the value of x is {x}')

We can circumvent this by using the keyword global before the variable name. Declaring global x will let us use the name x as if we were in the global namespace.

x = 5
def f():
# Declaring x as global allows us to modify
# its value in the global namespace
global x
x = 3
print(f'Before: the value of x is {x}')
f()
print(f'After: the value of x is {x}')

To access a variable in the closest enclosing namespace, we can use the keyword nonlocal.

However, using these keywords is generally considered bad practice. It is confusing to read code that uses objects outside of a modularized portion.


Actions that create namespaces

We mentioned that calling functions is one action that creates a new namespace. Are there others?

This is a common confusion for programmers who are used to another language, as rules for creating scopes differ between languages.

Actions that create scope in Python

  • Calling a function
  • Accessing attributes or functions of a class
  • Accessing objects in another module or package. Imported modules are objects, just like functions. Using a function or variable from an imported module creates a new namespace, just like calling a function.

Actions that do NOT create scope in Python

  • Entering an if statement
  • Entering a for or while loop
  • Creating a context manager

Conclusion

The LEGB rule names the possible scopes of a variable in Python: Local, Enclosing, Global, Built-in. Python searches namespaces in this order to determine the value of an object given its name.

Scopes are created with functions, classes, and modules. If we define objects with the same name in different scopes, they are isolated: at any point, the value of the name will be the value of the object in scope. Similarly, modifying an object by that name will only affect the object in scope.

However, we can explicitly circumvent the scope of a name using the keywords global and nonlocal. This is bad practice in most cases, but can occasionally simplify code.

RELATED TAGS

legb
scope
namespace
python
edpresso competition
Did you find this helpful?