Learn

While most of our focus so far has been around where we can access namespaces, to truly get a full picture of scoping rules, we must also examine how Python handles scope resolution.

Scope resolution is a term used to describe a search procedure for a name in the various namespaces. A set of rules dictates the order that the search needs to follow.

In Python, the unofficial rule (often referred to in literature but does not exist in the official documentation) is known as the LEGB rule.

LEGB stands for Local, Enclosing, Global, and Built-in. These four letters represent the order of namespaces Python will check to see if a name exists. Here is a visualization of the order:

LEGB Rule

To see this rule in action, let’s take a look at two specific scenarios where Python is searching for a name. The first scenario is a nested function that wants to print a variable called age:

age = 27 def func(): def inner_func(): print(age) inner_func() func()

Would output:

27

So what exactly happened here in terms of scope resolution? It went a bit like this:

  • First, Python looked in the local (The L of LEGB) scope that existed inside of inner_func(). This is the lowest level of the LEGB rule and thus where Python starts the search for a name that is trying to be called (in this case via a print()). Python then realized the name of age isn’t in the local namespace and continues the search to the upper levels of scope.

  • The second level Python examined is the enclosing scope (The E of LEGB) of func(). Unfortunately, again the name of age doesn’t exist in the enclosing namespace, and Python moves upwards to higher scopes.

  • Next, Python arrives at the global scope and finds the name of age in the global namespace. The search is finished, and the result is returned.

This process of scope resolution is crucial to understanding how programs are able to access names in different scopes. Keep in mind the order that Python searches always start at the lowest level (the local level) and always flows upward to the higher scopes.

The second scenario to examine is seeing what happens when we have two of the same name in different namespaces.

Let’s examine the same script but with a slight modification that creates a second name called age in a different namespace. Here is what it looks like:

age = 27 def func(): age = 42 def inner_func(): print(age) inner_func() func()

Here the output will be 42 because Python could find a name (age) in the enclosing scope and did not continue to search for the value up into the global scope. If Python cannot find a name in any of the four scopes it searches, it will return a NameError exception.

Instructions

1.

Using the LEGB rule, we are going to try and correct this function to behave how we expect it to. It should replace the color with a new provided color and print out the old and new colors. Try running the code to see what the first issue is.

2.

The LEGB rule starts with “Local”. Let’s take a look at any local variable issues that we could be running into. Looking at each of the local variables, we can see that to_update is local to the function disp_color(), but we attempt to access it from change_color().

Move the initialization of to_update so that the scope is local to change_color(). Try running the code now and see what happens.

3.

Now we are not getting any errors, but the output is not correct. There doesn’t seem to be any encompassing scope issues, but there is an issue with the global variable color.

We are using the global keyword to allow color to be modified in order to print the new color. If we look at the order of operations, we modify the global variable before calling disp_color().

To fix this, move the change to the variable color to after disp_color() is called but before the new color is output.

Run the code and see that happens!

Sign up to start coding

By signing up for Codecademy, you agree to Codecademy's Terms of Service & Privacy Policy.
Already have an account?