Programmer's Python - Local and Global
Written by Mike James   
Tuesday, 16 April 2024
Article Index
Programmer's Python - Local and Global
Inner Functions

Inner Functions

You can define a function anywhere in your code. When you first start with Python this generally means defining functions within a module, i.e. at the “top level”. However, there is nothing wrong with defining functions within the code of another function, for example:

def myFunction():
    def myInnerFunction():
        myInnerVariable=20
        print(myInnerVariable)
    
    myInnerFunction()    
myFunction()

Notice that myFunction contains a definition of another function, myInnerFunction. This has a single local variable, myInnerVariable, which it prints. Calling the outer function, myFunction, results in calling the inner function and the display of its local variable. As myInnerFunciton is a local variable and not an attribute, you cannot call myInnerFunction using a qualified name.

You can repeat this as many times as you like defining one function in the code of another. In practice it is rare for functions to be nested more than one deep, but there is nothing in Python that rules it out. Each function is local to the function that immediately contains its definition.

Local, Global and Nonlocal

This should be all very clear and obvious, but notice that in the example above we have created two function objects. The first, i.e. the one referenced by myFunction, comes into existence immediately. The second, i.e. the one referenced by myInnerFunction, only comes into existence when we call myFunction and its code is executed. Notice that the local variables for the inner function only exist while it is being executed and so there is no prospect of the outer function accessing them. However, the local variables of the outer function exist for the entire time that the inner function is executing – can it access them?

To pose the question another way, are the containing function’s local variables like globals to the inner function? The answer is yes, but it is far more involved a story than you might imagine. The reason is once again the fact that Python has no keyword for defining a variable. When you assign to a variable it is created if it doesn’t already exist in the local context. What this means is that the inner function can access the local variables of the outer function, but it cannot assign to them without taking an extra step.

 

Consider for example:

def myFunction():
    myOuterVariable=10
    def myInnerFunction():
        print(myOuterVariable)
    myInnerFunction()    
myFunction()

This accesses myOuterVariable as defined as a local variable of myFunction. However, if you assign to myOuterVariable within the inner function a local variable is created:

def myFunction():
    myOuterVariable = 10
    def myInnerFunction():
        myOuterVariable = 20
        print(myOuterVariable)
    myInnerFunction()
    print(myOuterVariable)
myFunction()

This prints 20 followed by 10, demonstrating that the inner function used its own local variable and didn’t use the outer variable.

If you want to assign to an outer variable you have to declare it as nonlocal. The nonlocal statement works like the global statement in that it stops assignment from creating a local variable, For example:

def myFunction():
    myOuterVariable = 10
    def myInnerFunction():
        nonlocal myOuterVariable
        myOuterVariable = 20
        print(myOuterVariable)
    myInnerFunction()
    print(myOuterVariable)
myFunction()

Declaring myOuterVariable as nonlocal stops the Python system from creating a new local variable and forces it to search for the variable in the variable table of the enclosing function. Now what you see printed is 20 followed by 20 as the variable defined in the outer function is used.

You might ask, what is the difference between nonlocal and global?

Declaring a variable as global within a function will either create the global variable or make use of the one already defined. Notice this has to be a global variable defined at the module level.

Declaring a variable as nonlocal within a function makes use of the variable defined within the containing function. If there isn’t one then the next containing function is used to supply the variable and so on. If no variable that is local to a containing function is found then an error occurs.

This means that a nonlocal declaration never creates a new variable and never makes use of a global variable. It searches any set of nested functions from the innermost and uses the first variable of the same name it finds. This might seem complicated but it is a perfectly logical consequence of Python defining a variable by assignment.

  • Use global in a function when you want to use or create a global variable.

  • Use nonlocal in a function when you want to use the first local variable available in the containing functions.

Included in book but not in this extract

  • Closure
  • A Common Error
  • What Use is Closure?
  • Private State Variables
  • Function Self Reference
  • Callbacks
  • Closures __closure__ and Cells (Advanced)

Summary

  • A variable that a function assigns to is created as a local variable.

  • To reference a global variable that a function assigns to, it has to be declared as global.

  • Functions can be defined within other functions and the inner functions have access to the containing function’s local variables, but not vice versa.

  • If an inner function assigns to a variable then it is created as a local variable.

  • To refer to a local variable of a containing function in an assignment you have to declare the variable nonlocal.

  • Closure is a natural consequence of function objects outliving their local variables. If an inner function exists and can be invoked after its containing function has ended, then it still has access to the same local variables via the closure.

  • The closure consists of all of the variables in scope when a function is declared – its execution context.

  • All functions declared within the same execution context share that context as their closure.

  • The values of variables in the closure are the last values they had before the outer function terminated.

  • Closures have many uses, but the main ones are to provide private state variables, provide a self-reference, and to provide context to callback functions.

  • You can work with the __closure__ magic attribute to access, and even change, the closure, but how this works is platform-dependent. Use the inspect module to isolate your code from such changes.

Programmer's Python
Everything is an Object
Second Edition

Is now available as a print book: Amazon

pythonObject2e360

Contents

  1. Get Ready For The Python Difference
  2. Variables, Objects and Attributes
  3. The Function Object
  4. Scope, Lifetime and Closure
      Extract 1: Local and Global ***NEW!
  5. Advanced Functions
  6. Decorators
  7. Class, Methods and Constructors
      Extract 1: Objects Become Classes 
  8. Inside Class
  9. Meeting Metaclasses
  10. Advanced Attributes
  11. Custom Attribute Access
  12. Single Inheritance
  13. Multiple Inheritance
  14. Class and Type
  15. Type Annotation
  16. Operator Overloading
  17. Python In Visual Studio Code

 Extracts from the first edition

<ASIN:1871962749>

<ASIN:1871962595>

<ASIN:1871962765>

Related Articles

Creating The Python UI With Tkinter

Creating The Python UI With Tkinter - The Canvas Widget

The Python Dictionary

Arrays in Python

Advanced Python Arrays - Introducing NumPy

espbook

 

Comments




or email your comment to: comments@i-programmer.info

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.

 



Last Updated ( Tuesday, 16 April 2024 )