Decorators

Contents

Decorators#

It’s a sugar that allows to modify behaviour of the functions or classes.

Syntax#

Decorator actually is just a function that takes fucntion and return other function.


The following cell defines a decorator, which is a function that takes another function as an argument and returns a modified version of that function. During the creation of the new function, it prints Functionality during function modification. Additionally, it prints Functionality to be added. each time the modified function is called.

def wrapper_function(modified_function):
    print("Functionality during function modification.")
    def inner_function():
        print("Functionality to be added.")
        modified_function()
    return inner_function

Now the most straighfoward way to use it. Here defined earlier wrapper_function is used for getting decorated_function which is modification of the function_to_decoration.

def function_to_decoration():
    print("Original functionality")

decorated_function = wrapper_function(function_to_decoration)
Functionality during function modification.

So during modification we got executed print("Functionality during function modification.").

decorated_function()
Functionality to be added.
Original functionality

Each call executes the functionality defined by inner_function, followed by the original function in function_to_decorate.

This may seem like playful experimentation with functions, but you can achieve the same result using the following syntax:

@wrapper_function
def function_to_decoration():
    print("Original functionality")
Functionality during function modification.

The code in the previous cell is equivalent to function_to_decorate = wrapper_function(function_to_decorate). As a result, the output behaves the same way as it did without using any special syntax.

function_to_decoration()
Functionality to be added.
Original functionality

Parameters#

Some popular and in some cases really convenient syntax passes arguments to decorators that determine their behaviour. It typically look like this:

@decorator(param=value)
def decorated(): ...

The result of the decorator(param) is returned to the @ operator and applied to the decorated fucntion.


The following cell defines a decorator called multiply, which extends a function that takes two floats by multiplying the result by a specified value.

def multiply(multiplier: float):
    def wrapper(func):
        def modifier(a: float, b: float):
            return func(a, b)*multiplier
        return modifier
    return wrapper

Technically, it’s a function with a multiplier parameter that returns another function, which in turn returns a final function that performs the multiplication.

The most straightforward way to apply it to a function is demonstrated in the following cell.

@multiply(3)
def summation(a: float, b: float) -> float:
    return a + b

Let’s try just created function.

summation(2, 3)
15
  • 2+3=5 functional of the function.

  • 5*3=15 function of the decorator.

The following cell break down the actual process into the steps:

  • Call of the multiply as a regular funciton, which returns the actual decorator.

  • Application of the actuall decorator to the summation.

actual_decor = multiply(3)

@actual_decor
def summation(a: float, b: float) -> float:
    return a + b

summation(2, 3)
15

The same output is achieved.