Sage-Code Laboratory
index<--

Python Closures

Closure is a higher order function that encapsulate one or several other functions. The enclosed functions have access to variables used when the function was created. This is called "context".Using closures is a high appreciated skill that can improve performance of your applications.

Python can be used as a functional programming language. In Python you can create functions that will produce as a result another function. That technique is useful to create light-weight code without using object oriented programming.

Example:

Next example is a function that create another function called "test_closure"


# Create a closure
def test_closure(max):
    index = {1:-1} # mutable attribute
    def enclosed():
        if index[1] <= max:
           index[1] += 1
           return index[1]
        else:
           return -1
    return enclosed

def main():
    # use closure based function my_scan()
    my_scan = test_closure(5);
    for i in range(0,5):
        print(i,'->',my_scan())

# program entry point
if __name__ == "__main__":
    main()

Note: In python context variables are read only. However there is a workaround to help resolve this issue: You can use a dictionary or a list with a single element. The elements enclosed into any container can be read and write. In the example, index is a mutable attribute. Nice trick isn't it?

Using Closure

We use closure like a poor man class to generate function instances. This is the secret, we encapsulate one or several states with the closer function. This is helping to create similar functions at runtime based on different parameter values that can hold a state. Closures can help to avoid polluting the global scope with variables that can become hard to track.

test_closure(max)

In the example above function test_closure is a closure function because it returns a function enclosed.This function is captured using closure invocation: my_scan = test_closure(5);

my_scan()

Function my_scan is a function instance because it was created out of enclosure at runtime. Once instantiated my_scan function can be used like any other function. It is like a generator. Returns next number each time is called up to 5 then will return -1.

0 -> 0
1 -> 1
2 -> 2
3 -> 3
4 -> 4

Homework: Try to run this example live: python closure


Read next: Python 3.8 Doc