Introduction to decorators
Functions III showed that functions are values: you can pass them around and return them. Decorators are the natural next step: a small wrapper function that takes another function in, adds some behaviour, and returns a replacement. The @ symbol is just a shortcut for that pattern.
In Functions III you saw that functions are values: you can pass them as arguments and return them from other functions. A decorator builds on that idea.
Take an existing function and a wrapper that adds extra behaviour around it:
shout takes a function in, defines a small wrapper around it, and returns the wrapper. Calling loud() actually runs wrapper(), which calls greet() and uppercases the result.
What will be the output?
Reassigning the result back to the original name is so common that Python has a shortcut. The @ syntax does exactly the same thing.
These two snippets are equivalent:
What will be the output?
The wrapper can do anything: print before and after, change the result, or skip the call entirely. The original function isn't modified, it's replaced by the wrapper.
A wrapper that prints around the call:
What will be the output?
Decorator structure to memorise:
What will be the output?
What will be the output?
What will be the output?