Get startedGet started for free

Nested functions

1. Nested functions

Now that you've come to grips with scope, both local and global, it's time to dive a bit deeper!

2. Nested functions (1)

What if we have a function inner defined within another function outer and we reference a name x in the inner function? The answer is intuitive: Python searches the local scope of the function inner, then if it doesn't find x, it searches the scope of the function outer, which is called an enclosing function because it encloses the function inner. If Python can't find x in the scope of the enclosing function, it only then searches the global scope and then the built-in scope. But whoa, hold on there for a second, why are we even nesting functions?

3. Nested functions (2)

There are a number of good reasons to do so. Let's say that we want to use a process a number of times within a function. For example, we want a function that takes 3 numbers as parameters and performs the same function on each of them. One way would be to write out the computation 3 times

4. Nested functions (3)

but this definitely does not scale if you need to perform the computation many times. What we can do instead is define an inner function within our function definition, such as we do here, and call it where necessary. This is called a nested function. The syntax for the inner function is exactly the same as that for any other function.

5. Returning functions

Let's now look at another important use case of nested functions. In this example, we define a function raise_vals, which contains an inner function called inner. Now look at what raise_vals returns: it returns the inner function inner! raise_vals takes an argument n and creates a function inner that returns the nth power of any number. That's a bit complicated and will be clearer when we use the function raise_vals. Passing the number 2 to raise_vals creates a function that squares any number. Similarly, passing the number 3 to raise_vals creates a function that cubes any number. One interesting detail: when we call the function square, it remembers the value n=2, although the enclosing scope defined by raise_val and to which n=2 is local, has finished execution. This is a subtlety referred to as a closure in Computer Science circles and shouldn't concern you too much. It is worth mentioning, however, as you may encounter it out there in the wild.

6. Using nonlocal

Recall from our discussion of scope that you can use the keyword global in function definitions to create and change global names; similarly, in a nested function, you can use the keyword nonlocal to create and change names in an enclosing scope. In this example, we alter the value of n in the inner function; because we used the keyword nonlocal, it also alter the value of n in the enclosing scope. This is why calling the function outer prints the value of n as determined within the function inner. You'll have practice using the keyword nonlocal in the interactive exercises.

7. Scopes searched

To summarize: name references search at most four scopes, the local scope, then those of enclosing functions, if there are any; then global, then built-in. This is known as the LEGB rule, where L is for local, E for enclosing, G for global and B for built-ins! Also, remember that assigning names will only create or change local names, unless they are declared in global or nonlocal statements using the keyword global or the keyword nonlocal, respectively.

8. Let's practice!

Now it's your turn to write some nested functions. Enjoy!