Decorators

Decorators are a structural design pattern which wrap the original object, to add extra functionality dynamically, without modifying the original object. Decorators are usually used to run code before and/or after a function. Thus, they decorate the function with additional functionality, without changing the original function. They can also be used to alter the functionality of methods and classes.

Creating Decorators

Functions in Python are first class objects: they can be assigned to variables, passed into functions as arguments, returned from functions and declared inside functions.

With that in mind, a decorator can be created using functions or classes.

Decorator using Functions

The general syntax for creating a decorator using functions is as follows:

Loading...

The original_function(), in this case, is the function that is decorated with the decorator_name().

For example, a decorator that upper cases the returned values from any function can be created as follows:

Loading...

Decorator using Classes

The general syntax for creating a decorator using classes is as follows:

Loading...

For example, a decorator created using class based syntax that upper cases the return values from any function:

Applying Decorator to a Function

The decorators created above accept an argument called original_function which can be any function. Therefore, we create a greeting() function and decorate it with the @upper_case_decorator.

Loading...

greeting() function can be decorated with the common python syntax by calling the decorator function and assigning the result back to greeting.

Loading...

However, Python provides a simpler way to achieve the same result using the @ symbol syntax. Add the line @upper_case_decorator at the start of function definition to decorate it.

Loading...

@upper_case_decorator or @upper_case_decorator_with_class can be used to decorate other functions as well.

Loading...

The full code with a decorator created using function will be:

Passing arguments to the Decorated functions

Arguments can be passed to the original function by creating parameters in the wrapper() function.

Eg: arg1 is the parameter that the original function greeting() requires. Thus, the wrapper() function receives it and passes it along to the original function call.

General purpose decorators can be also be created that can accept any number of arguments by packing positional arguments using *args and by packing keyword arguments using **kwargs.

Loading...

An example of variable arguments accepting decorator is as follows:

Passing Arguments to Decorators

Arguments can also be passed to the decorator itself. To pass arguments to the decorator, there should be a decorator_wrapper_to_accept_decorator_arguments() function wrapping the original decorator.

Loading...

Eg: With the greeting function, the decorator could be setup to use a number_of_times_to_greet parameter to greet once or more than once.

Loading...

Even though, greeting() and greeting_twice() have the exact same function definition, their outputs are different because the decorator is executing these functions as per the number_of_times_to_greet argument passed to the decorator.

help() with Decorators

The original function name and docstring are lost when it’s wrapped by a decorator.

The name of the function is greeting() and not wrapper(). The decorator completely hides the function and it’s docstring. This also means that the help(greeting) call will be completely useless since it’ll have no information about the greeting() function.

To solve this problem, python provides a decorator. @functools.wraps() decorator can be used to decorate the wrapper() function.

Example Decorators

Decorators can be used to measure the performance of a function

Decorators are used to create specialized functions

Special functions like ‘once’ that would only execute one time even if they’re called more than once, can be created using decorators.

Interested in contributing to Codecademy Docs? Check out our Contribution Guide or leave us some feedback.

Learn Python on Codecademy