Décorateurs Python
Un décorateur est une fonctionnalité avancée de Python utilisée pourétendre dynamiquement les fonctionnalités de fonctions ou de classes sans modifier le code d'origine de la fonction。
Essentiellement, un décorateur est une fonction : il reçoit une fonction comme argument et renvoie une nouvelle fonction (généralement une version améliorée de la fonction d'origine).
Les décorateurs sont appliqués à l'aide de la syntaxe@decorator_nameplacée avant la définition d'une fonction ou d'une méthode.
Python fournit également quelques décorateurs intégrés, tels que@staticmethodet@classmethod。
Cas d'utilisation courants :
- Journalisation :Enregistrer les informations d'appel de fonction, les paramètres et les valeurs de retour
- Statistiques de performance :Mesurer le temps d'exécution d'une fonction
- Contrôle d'accès :Restreindre les autorisations d'accès aux fonctions
- Mise en cache :Mettre en cache les résultats de fonctions pour améliorer les performances
Syntaxe de base
L'idée centrale d'un décorateur est :utiliser une fonction pour "envelopper" une autre fonction。
Syntaxe
def wrapper(*args, **kwargs):
# Avant l'appel
print("Avant l'exécution")
result = original_function(*args, **kwargs)
# Après l'appel
print("Après l'exécution")
return result
return wrapper
@decorator_function
def target_function():
print("Exécution de la fonction originale")
Explication :
decorator_function: fonction décoratrice (reçoit la fonction originale)wrapper: fonction d'encapsulation (réellement exécutée)@decorator_function: équivalent à un remplacement de fonction
Forme équivalente :
target_function = decorator_function(target_function)
👉 Lors de l'appeltarget_function(), ce qui est réellement exécuté estwrapper()
Utilisation des décorateurs
Les décorateurs sont appliqués à l'aide du@sucre syntaxique placé avant la définition de la fonction :
@time_logger
def target_function():
pass
Équivalent à :
def target_function():
pass
target_function = time_logger(target_function)
Ce mécanisme nous permet d'ajouter uniformément des fonctionnalités (telles que la journalisation, les autorisations, etc.) sans modifier la fonction d'origine.
Exemple : affichage des journaux
def wrapper():
print("Avant l'exécution de la fonction")
func()
print("Après l'exécution de la fonction")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
Sortie :
函数执行前 Hello! 函数执行后
my_decoratorReçoitsay_hello@my_decoratorRemplace la fonction d'origine
Décorateurs avec paramètres
Si la fonction d'origine a des paramètres, vous devez, dans lewrapperuse*args, **kwargs:
Exemple
def wrapper(*args, **kwargs):
print("Avant l'exécution")
func(*args, **kwargs)
print("Après l'exécution")
return wrapper
@my_decorator
def greet(name):
print(f"Bonjour, {name}!")
greet("Alice")
Sortie :
执行前 Hello, Alice! 执行后
Explication :Utilisation*args, **kwargspeut accepter des fonctions avec un nombre quelconque de paramètres.
Décorateurs avec paramètres (avancé)
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(3)
def say_hello():
print("Hello!")
say_hello()
Explication :Il s'agit d'une "fabrique de décorateurs" ; la fonction externe est utilisée pour recevoir des paramètres.
Hello! Hello! Hello!
Décorateurs de classe
En plus des fonctions, les décorateurs peuvent également être appliqués aux classes.
Un décorateur de classe reçoit une classe et renvoie une classe modifiée ou une classe enveloppe.
- Améliorer les méthodes de classe
- Contrôler le processus d'instanciation
- Implémenter des fonctionnalités telles que les singletons et la journalisation
Décorateurs de classe basés sur des fonctions
Exemple
class Wrapper:
def __init__(self, *args, **kwargs):
self.wrapped = cls(*args, **kwargs)
def __getattr__(self, name):
return getattr(self.wrapped, name)
def display(self):
print("Avant l'appel")
self.wrapped.display()
print("Après l'appel")
return Wrapper
@log_class
class MyClass:
def display(self):
print("Méthode originale")
obj = MyClass()
obj.display()
Before call Original method After call
Décorateurs de classe basés sur des classes
Exemple : patron Singleton
def __init__(self, cls):
self.cls = cls
self.instance = None
def __call__(self, *args, **kwargs):
if self.instance is None:
self.instance = self.cls(*args, **kwargs)
return self.instance
@SingletonDecorator
class Database:
def __init__(self):
print("Initialisation")
db1 = Base de données()
db2 = Base de données()
print(db1 is db2)
初始化 True
Décorateurs intégrés
Décorateurs intégrés couramment utilisés :
- @staticmethod: définit une méthode statique
- @classmethod: définit une méthode de classe
- @property: transforme une méthode en propriété
Exemple
@staticmethod
def static_method():
print("Méthode statique")
@classmethod
def class_method(cls):
print(cls.__name__)
@property
def name(self):
return self._name
@name.setter
def name(self, value):
self._name = value
Superposition de plusieurs décorateurs
Plusieurs décorateursenveloppent la fonction du bas vers le haut pendant la phase de définition,et s'exécutent du haut vers le bas pendant la phase d'appel:
Exemple
def wrapper():
print("Décorateur 1")
func()
return wrapper
def decorator2(func):
def wrapper():
print("Décorateur 2")
func()
return wrapper
@decorator1
@decorator2
def say_hello():
print("Hello!")
say_hello()
Sortie finale :
Decorator 1 Decorator 2 Hello!
Résumé essentiel
Decorator = a function that wraps a function + extending functionality without modifying the original code
- La syntaxe @ est essentiellement un remplacement de fonction
- wrapper est la fonction qui est réellement exécutée
- Il est recommandé d'utiliser *args, **kwargs pour une plus grande polyvalence
- Prend en charge les fonctions, les classes et même les décorateurs avec paramètres