Closures and decorators

Functions, lesson 7 of 8

🧩 Functions, lesson 7 of 8

Closures and decorators

Build functions that remember variables, and wrap functions with decorators.

12 min

1 exercise

2 quizzes

0/3 solved

Getting Python ready… examples can run in a moment.

A function can be defined inside another function. The inner function can use the outer function's variables, and it keeps them even after the outer function has returned. A function together with the variables it uses is a closure.

Example

A greeter factory

make_greeter returns greet itself, without calling it. hi and hola each remember their own greeting.

Inside a function, reading an outer variable works. Assigning to it does not: count += 1 makes a new local count, as you saw in the scope lesson. To rebind a variable from the enclosing function, declare it with nonlocal. (global would mean a module-level variable instead.)

Example

A counter that remembers

bump keeps count between calls. Remove the nonlocal line and the code fails.

Quiz

What does this print?

A decorator is a function that takes a function and returns a wrapped version of it. The wrapper usually calls the original and adds something before or after. Here is one written by hand:

Example

Shout, by hand

greet is unchanged. loud_greet is the wrapper: it calls greet and shouts the result.

Example

The @ shorthand

@shout on the line above the def means exactly greet = shout(greet). The @property and @dataclass you'll meet in the OOP module, and @lru_cache in the algorithms module, are decorators too.

Quiz

What does this print?

Exercise

Counter and doubler

Two parts:

  1. Write make_counter(). It returns a function that returns the next number each time it is called: 1, 2, 3, ... Every counter keeps its own count. Use nonlocal.
  2. Write a decorator doubled(func). It returns a wrapper that calls func with the same arguments and returns twice the result. The wrapper must accept any number of arguments.