Functions II

Nested Functions and Enclosing Scope

Learn about the enclosing scope, which allows nested functions to access variables defined in their outer (enclosing) function.


We've already learnt that functions can access variables defined in their own local scope, as well as in the global scope.

#### global scope #### ... def my_function(): #### local scope #### ...
Python

When we are dealing with nested functions, there's an additional type of scope: the so-called enclosing scope.

The enclosing scope refers to the region where the outer function's variables are accessible by the inner (nested) function.

Even though the inner function has its own scope, it can still access variables from the outer function.

From the perspective of the inner function, there are 3 different scopes:

#### global scope #### ... def outer(): #### enclosing scope #### ... def inner(): #### local scope #### ...
Python

That means the inner function can access variables defined in the global scope...

#### global scope #### global_var = 'global' def outer(): #### enclosing scope #### def inner(): #### local scope #### print(global_var) inner() outer()
Python
Output

And variables defined in the enclosing scope...

#### global scope #### def outer(): #### enclosing scope #### enclosing_var = 'enclosing' def inner(): #### local scope #### print(enclosing_var) inner() outer()
Python
Output

And variables defined in its own local scope...

#### global scope #### def outer(): #### enclosing scope #### def inner(): local_var = 'local' #### local scope #### print(local_var) inner() outer()
Python
Output

In Python, the way variables are looked up follows a specific order, or hierarchy.

This hierarchy determines where Python starts looking for variable names.

The order goes from inside to outside:

Local Scope > Enclosing Scope > Global Scope
Python

This order is important when multiple variables with the same name exist in different scopes.

For example, in this case, the local version of x takes precedence over the others:

x = 'global' def outer(): x = 'enclosing' def inner(): x = 'local' print(x) inner() outer()
Python
Output

If there's no local version of x, the enclosing version takes precedence over the global one:

x = 'global' def outer(): x = 'enclosing' def inner(): print(x) inner() outer()
Python
Output

What will be the output?

x = 10 def outer(): y = 20 def inner(): z = 30 print(x, y, z) inner() outer()
Python

What will be the output?

x = 10 def outer(): x = 20 def inner(): x = 30 print(x) inner() outer()
Python

What will be the output?

x = 10 def outer(): x = 20 def inner(): x = 30 print(x) inner() outer()
Python

What will be the output?

x = 10 def outer(): x = 20 def inner(): x = 30 inner() print(x) outer()
Python

What will be the output?

x = 10 def outer(): x = 20 def inner(): print(x) inner() outer()
Python