AMZ DIGICOM

Digital Communication

AMZ DIGICOM

Digital Communication

A Quick Tour of Python Decorators

PARTAGEZ

Python Decorators allow you to increase your influence over the basic functionality of a function without changing the source code on which it is based.

Function decorators: what are they and what are they used for?

Using Python Decorators is not covered in detail in most Python tutorials. You wonder why ? To understand function decorators, it is first necessary to understand the functions themselves. In code, Python Decorators are recognizable by their own Python operator: this is the “@” symbol, followed by the name of the function decorator.

The following code example shows the basic syntax for calling the Python Decorator, but no functionality is implemented:

@decorator
def fonction():
 pass

Python

In this example, the code saved as “decorator” would be executed when the function named “function” is called.

Often, function decorators are also used as part of object-oriented programming with Python. For example, there is a Python Property decorator, used as an equivalent of the “getter” and “setter” methods in other programming languages.

The Python programming language is perfect for web projects, among other things thanks to its practical solutions (like function decorators). The Deploy Now tool, offered by IONOS, also lends itself very well to the realization of Web projects. The Deploy Now tool allows you to easily create and deploy your project using GitHub, so you can have an overview of your project at all times.

Python Decorators: Usage

Improve basic functionality with Python Decorators

In most cases, Python Decorators are used to improve the basic functionality of a function. This solution can be useful if you use the same basic function within the framework of different use cases and want to improve it in certain situations only. Below is a sample code that is simple, but ready to run. Learn how to use a Python Decorator to enhance a feature:

def dec(fonction):
 def foo(x):
  print("Avant l'appel de la fonction de" + fonction.__nom__)
  fonction(x)
          print("Avant l'appel de la fonction de" + fonction.__nom__)
 return foo

@dec
def bar(y):
 print("Appel de la fonction bar avec la valeur" + str(y))

bar("Test")

Python

In this sample code, we start by creating the decorator named “dec”; this contains a function with the name “foo”. As you can see, the function decorator is ultimately nothing more than a standalone “wrapper” function. In our case, it contains another function named “foo”. In this “foo” function, we must begin by indicating that we are before the call to the function passed to the decorator in the “function” parameter. The function of the parameter is then executed. A new call to Python’s “print” function is then made; it indicates that we are after the call of the function registered as a parameter.

The second part of the code includes a definition of the function called “bar”, which receives a transfer parameter named “y”. It is easy to understand the functionality of “bar”: it displays on the screen the sentence “Call of the function bar with the value y”, using for “y” the value passed as a parameter. The “bar” function has the particularity of being “decorated”. You can see it in the sample code, on the “@dec” line, before the function definition.

But what exactly happens when a function has been “decorated”? Let’s say we didn’t specify the Python Decorator, namely the “@dec” line of code. Calling the “bar” function, which ends our example code, would then give the following result:

Appel de la fonction bar avec la valeur Test

Python

Here, exactly what is expected for a function call happens: the Python string “Test”, passed for the “y” parameter, is inserted into the “print” declaration. The result of the function therefore reflects this action.

Now let’s recreate the result of the same call to the “bar” function, this time being “decorated” using our Python Decorator:

Avant l'appel de la fonction bar
Appel de la fonction bar avec la valeur Test
Après l'appel de la fonction bar

Python

What you see then may surprise you: once “decorated”, our function no longer only displays on the screen the result of its own “print” declaration. In fact, the result of our function decorator has been “encapsulated”, so that the two “print” declarations of the “foo” auxiliary function are also taken into account. The main functionality of the “bar” function has therefore been improved by the introduction of two additional “print” results, thanks to the use of the Python Decorator.

This example remains of course artificial and does not fit into any in-depth programming logic. It should, however, help you better understand how Python Decorators work. It goes without saying that you can integrate the Python functionality of your choice into the “Decorator” function.

Python Decorators: extract recurring conditions

You may want to condition the execution of some of your functions. To do this, the “if…else” statements in Python are probably already familiar to you. If these conditions must be checked in different places, it may however be wise, to guarantee the readability of your code, to externalize this condition by using a Python Decorator.

The sample code below should help you visualize how you can use your Python Decorator. Some mathematical operators are only defined on natural numbers; a function decorator responsible for checking whether or not the transfer parameter of a function corresponds to a natural number could therefore be useful to you.

def nombre_naturel(fonction):
 def test(x):
  if type(x) == int and x > 0:
   return fonction(x)
  else:
   raise Exception("L'argument n'est pas un nombre naturel")

@nombre_naturel
def fac(n):
 if n == 1:
  return 1
 else:
  return n * fac(n-1)

print(fac(5))
print(fac(-1))

Python

In the code above, we start by defining our Python Decorator called “natural_number”. It is used to check whether the argument of the function passed to it (“function”) corresponds or not to a natural number. To do this, the “if” condition first checks the type of the argument. A test is also performed to determine if the argument is a positive number greater than 0. If so, the function passed to the decorator as a parameter is executed. Otherwise, an exception stating that the function argument is not a natural number is thrown.

In practice, the operation of our Python Decorator can be illustrated by observing the function it “decorates”, called “fac”. This is defined in the code and called a first time with the value “5”, then a second time with the value “-1”. The result then looks like this:

120
Traceback (most recent call last):
  File "<pyshell#17>", line 1, in <module>
    fac(-1)
  File "<pyshell#11>", line 6, in test
    raise Exception("L'argument n'est pas un nombre naturel")
Exception: L'argument n'est pas un nombre naturel

Python

First you see the number “120”, which is the factorial of 5. So the factorial function works for natural numbers. Calling this factorial function with a negative number, however, results in an error…due to the Python Decorator! Since a negative number is not a natural number, the factorial function should not be performed here.

Télécharger notre livre blanc

Comment construire une stratégie de marketing digital ?

Le guide indispensable pour promouvoir votre marque en ligne

En savoir plus

Souhaitez vous Booster votre Business?

écrivez-nous et restez en contact