Langage Python

les décorateurs en python

Les décorateurs sont des outils très puissants et utiles en Python, car ils permettent aux programmeurs de modifier le comportement d'une fonction ou d'une classe. Les décorateurs nous permettent d’envelopper(wrapper) une autre fonction afin d’étendre le comportement de la fonction enveloppée, sans la modifier de façon permanente.

Dans Decorators, les fonctions sont prises comme argument dans une autre fonction, puis appelées à l'intérieur de la fonction wrapper.
Nous utilisons @func_name pour spécifier un décorateur à appliquer à une autre fonction.

def decorateur(fun):

    # fonction interne qui affiche bonjour avant l'appel de la fonction
    def hello(para):
        return "Bonjour "+fun(para)
        
    return hello

@decorateur
def Test(nom): 
    return nom

print(Test("Mostafa"))

# -> Bonjour Mostafa

Attacher des données

Les décorateurs peuvent également être utiles pour attacher des données (ou ajouter un attribut) à des fonctions.

    def add_data(func):
        func.donnee=5
        return func

    @add_data
    def somme(x,y):
        return x+y
    
    print(somme(3,4))
    print(somme.donnee)

'somme()' retourne la somme de x et y passée en arguments mais il est encapsulé par une fonction décoratrice

  • appeler somme(3, 4) donnerait simplement la somme de deux nombres
  • mais lorsque nous appelons 'somme.donnee', alors la fonction 'somme()' est passé dans la fonction décoratrice 'add_data' en argument et cette fonction retourne la fonction 'somme' avec un attribut 'donnee' avec une valeur de 5.

Temps d'exécution d'une fonction

import time 
  
# decorateur pour calculer le temps d'exécution d'une fonction
def Temps_execution(func): 

    # *args récupérer la liste des arguments
    # **kwargs récupérer les arguments (clé : valeur)
    def calculer(*args, **kwargs): 
  
        # début d'execution
        begin = time.time() 
          
        func(*args, **kwargs) 
  
        # fin d'execution
        end = time.time() 
        print("le temps d'execution de la fonction {} est {}: ".format(func.__name__, end - begin)) 
  
    return calculer 
  
  
  
@Temps_execution
def factorial(num): 
    f=1
    for i in range(2,num+1):
        f*=i
    print(f)
  
factorial(70)

Décorateurs avec paramètres

Syntaxe
        @nom_decorateur(params)
        def nom_fonction():
            ''' Function implementation'''
    
# Decorateur avec parametres 
def decorateur(*args, **kwargs): 

    def hello(func): 
        print("annee : ",args[0]) 
        print("Site : ", kwargs['site'])  
        print("ville : ", kwargs['ville']) 
        return func 
    return hello 
  
@decorateur(2019, site = "Developpement-informatique.com", ville="Meknès") 
def TEST(): 
    print("fonction test") 
  
TEST() 

Mémorisation à l'aide de décorateurs

La récursivité est une technique de programmation dans laquelle une fonction s’appelle de manière répétée jusqu’à ce qu’une condition de terminaison soit remplie.
Parmi les exemples où la récursivité est utilisée, citons: calcul de séries de fibonacci, factorielles, etc.
Mais le problème avec ces dernières est que dans l’arbre de récursivité, il est possible que le sous-problème déjà résolu soit à nouveau résolu, ce qui ajoute à une surcharge

La mémorisation est une technique d’enregistrement des résultats intermédiaires afin d’éviter des calculs répétés et d’accélérer les programmes.
Il peut être utilisé pour optimiser les programmes utilisant la récursivité.
En Python, la mémorisation peut être réalisée à l'aide des fonctions décoratrices.

Exemple : suite de fibonacci
            # décorateur de mémorisation
            def memo_fib(func): 
                memoire = {} 
              
                # Récupérer l'élément si il est déjà enregistré
                # calculer sinon
                def calculer(num): 
                    if num not in memoire:          
                        memoire[num] = func(num) 
                    return memoire[num] 
              
                return calculer 
                  
            @memo_fib
            def fib(num): 
                if num <2 : 
                    return 1
                else: 
                    return fib(num-1)+fib(num-2)
              
            print(fib(5)) 
    
  • memo_fib : L’objectif principal est de stocker les résultats intermédiaires dans la variable appelée mémoire.
  • La deuxième fonction appelée fib est la fonction permettant de calculer la suite de fibonacci. Il a été annoté par un décorateur (la fonction memo_fib). la fonction fib a accès à la variable de memoire grâce au concept de fermeture.
  • Lorsque fib(5) est appelé, les opérations récursives ont lieu en plus du stockage des résultats intermédiaires. Chaque fois qu'un calcul doit être effectué, il est vérifié si le résultat est disponible en mémoire. Si oui, alors il est utilisé, sinon, la valeur est calculée et stockée en mémoire.

Partager ce cours avec tes amis :
Rédigé par Mostafa Sedoki
Professeur d'Informatique dans les CPGE

Cours Similaires :