Introduction
Cette section présente le concept d'un décorateur. Il s'agit d'un sujet avancé dont nous ne ferons que frôler la surface.
This tutorial is from open-source community. Access the source code
💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici
Cette section présente le concept d'un décorateur. Il s'agit d'un sujet avancé dont nous ne ferons que frôler la surface.
Considérez une fonction.
def add(x, y):
return x + y
Maintenant, considérez la fonction avec une certaine journalisation ajoutée.
def add(x, y):
print('Appel de add')
return x + y
Maintenant, une deuxième fonction également avec une certaine journalisation.
def sub(x, y):
print('Appel de sub')
return x - y
Observation : C'est un peu répétitif.
Écrire des programmes avec beaucoup de duplication de code est souvent vraiment ennuyeux. Ils sont fastidieux à écrire et difficiles à maintenir. En particulier si vous décidez que vous voulez changer la manière dont il fonctionne (c'est-à-dire, peut-être un autre type de journalisation).
Peut-être que vous pouvez créer une fonction qui ajoute la journalisation à d'autres fonctions. Un wrapper.
def logged(func):
def wrapper(*args, **kwargs):
print('Appel de', func.__name__)
return func(*args, **kwargs)
return wrapper
Maintenant, utilisez-la.
def add(x, y):
return x + y
logged_add = logged(add)
Que se passe-t-il lorsque vous appelez la fonction renvoyée par logged
?
logged_add(3, 4) ## Vous voyez le message de journalisation apparaître
Cet exemple illustre le processus de création d'une fonction dite wrapper.
Un wrapper est une fonction qui s'enveloppe autour d'une autre fonction avec quelques traitements supplémentaires, mais qui fonctionne exactement de la même manière que la fonction d'origine.
>>> logged_add(3, 4)
Appel de add ## Sortie supplémentaire. Ajoutée par le wrapper
7
>>>
Nota : La fonction logged()
crée le wrapper et le renvoie en résultat.
Mettre des wrappers autour de fonctions est extrêmement courant en Python. Tellement courant qu'il existe une syntaxe spéciale pour cela.
def add(x, y):
return x + y
add = logged(add)
## Syntaxe spéciale
@logged
def add(x, y):
return x + y
La syntaxe spéciale effectue exactement les mêmes étapes que celles montrées ci-dessus. Un décorateur n'est qu'une nouvelle syntaxe. On dit qu'il décore la fonction.
Il y a bien plus de détails subtils sur les décorateurs que ceux présentés ici. Par exemple, les utiliser dans des classes. Ou utiliser plusieurs décorateurs avec une fonction. Cependant, l'exemple précédent est une bonne illustration de la manière dont leur utilisation tend à apparaître. En général, c'est en réponse à du code répétitif apparaissant dans une large gamme de définitions de fonctions. Un décorateur peut déplacer ce code vers une définition centrale.
Si vous définissez une fonction, son nom et son module sont stockés dans les attributs __name__
et __module__
. Par exemple :
>>> def add(x,y):
return x+y
>>> add.__name__
'add'
>>> add.__module__
'__main__'
>>>
Dans un fichier timethis.py
, écrivez une fonction décoratrice timethis(func)
qui entoure une fonction d'une couche supplémentaire de logique qui imprime le temps qu'il prend pour une fonction s'exécuter. Pour ce faire, vous entourerez la fonction d'appels de chronométrage comme ceci :
start = time.time()
r = func(*args,**kwargs)
end = time.time()
print('%s.%s: %f' % (func.__module__, func.__name__, end-start))
Voici un exemple de fonctionnement de votre décorateur :
>>> from timethis import timethis
>>> @timethis
def countdown(n):
while n > 0:
n -= 1
>>> countdown(10000000)
__main__.countdown : 0.076562
>>>
Discussion : Ce décorateur @timethis
peut être placé devant n'importe quelle définition de fonction. Ainsi, vous pouvez l'utiliser comme outil de diagnostic pour l'optimisation des performances.
Félicitations ! Vous avez terminé le laboratoire sur les décorateurs de fonctions. Vous pouvez pratiquer d'autres laboratoires sur LabEx pour améliorer vos compétences.