Décorateurs Python et modèle de conception de décorateur : les principales différences
Comparez les décorateurs Python et le modèle de conception de décorateur classique. Comprenez les différences entre l'encapsulation de fonctions au moment de la définition et la composition d'objets dynamiques d'exécution avec du code exécutable.
Bien que les décorateurs Python et le modèle de conception du décorateur partagent le même nom et le concept général de « enveloppement » du code pour étendre le comportement, ils représentent des constructions et des philosophies complètement différentes en matière de programmation.
Un décorateur Python est une fonctionnalité du langage, un sucre syntaxique qui vous permet d'encapsuler une fonction, une méthode ou une classe au moment de la définition. Il s'agit d'une forme de métaprogrammation qui s'exécute lorsque le module est importé ou défini, modifiant ainsi le comportement de cette fonction pour le reste de l'exécution de l'application.
Le modèle de conception Decorator, initialement défini par le Gang of Four (GoF), est un modèle de conception structurelle orienté objet. Il est conçu pour ajouter des responsabilités à des objets individuels de manière dynamique au moment de l'exécution, sans affecter les autres objets de la même classe, en utilisant des classes wrapper et une composition dynamique.
Matrice de comparaison des fonctionnalités
| Feature | Python | Other Language |
|---|---|---|
| Concept de base | Sucre syntaxique au niveau du langage pour encapsuler les fonctions/classes. | Modèle de conception pour ajouter dynamiquement un comportement à des objets individuels. |
| Temps d'exécution | Temps de définition (s'exécute une fois lorsque le module est chargé). | Runtime (instancié dynamiquement lors de l'exécution du programme). |
| Entité cible | Fonctions, méthodes ou classes entières (portée statique). | Instances d'objet spécifiques (portée dynamique). |
| Méthode de mise en œuvre | Fermetures et fonctions d'assistance utilisant la syntaxe `@decorator`. | Héritage de classe, alignement d'interface et composition d'objets. |
Syntax & Idiom Comparisons
01.Décorateur Python : Wrapper de fonctions (temps de définition)
Les décorateurs Python profitent de fonctions de première classe pour intercepter les appels. Lorsque vous écrivez `@my_decorator`, Python transmet la fonction décorée à votre fonction décorateur et lie la fonction wrapper renvoyée au nom de la fonction d'origine.
Dans cet exemple, le décorateur `@log_call` encapsule une fonction simple pour suivre quand elle est exécutée et ce qu'elle renvoie. Notez que cet emballage est gravé dans le marbre au moment où la fonction est définie.
def log_call(func):
def wrapper(*args, **kwargs):
print(f"[LOG] Executing '{func.__name__}' with args {args}")
result = func(*args, **kwargs)
print(f"[LOG] '{func.__name__}' returned: {result}")
return result
return wrapper
@log_call
def add(a, b):
return a + b
# The wrapping occurs once at definition time
print("Result of add(5, 7):", add(5, 7))// Decorators in Python are syntactic sugar for function wrappers:
// add = log_call(add)
// They exist primarily to avoid duplicate boilerplate for logging, timing, and auth.02.Modèle de conception de décorateur : enveloppement d'objet (composition d'exécution)
Le modèle de conception classique du décorateur utilise la composition des classes. Vous disposez d'une classe de composant de base et de classes de décorateurs qui enveloppent ce composant de base. Au moment de l'exécution, vous enchaînez ces constructeurs pour créer dynamiquement un objet personnalisé.
Ici, nous implémentons un système de décoration de café classique. Nous pouvons envelopper un objet Coffee de base dans un MilkDecorator et l'envelopper dans un SugarDecorator, en calculant le coût final de manière dynamique au moment de l'exécution.
class Coffee:
def get_cost(self):
return 5.0
def get_description(self):
return "Simple Coffee"
class MilkDecorator:
def __init__(self, coffee):
self.coffee = coffee
def get_cost(self):
return self.coffee.get_cost() + 1.5
def get_description(self):
return self.coffee.get_description() + ", Milk"
class SugarDecorator:
def __init__(self, coffee):
self.coffee = coffee
def get_cost(self):
return self.coffee.get_cost() + 0.5
def get_description(self):
return self.coffee.get_description() + ", Sugar"
# Chaining wrappers dynamically at runtime
my_drink = Coffee()
my_drink = MilkDecorator(my_drink)
my_drink = SugarDecorator(my_drink)
print("Drink description:", my_drink.get_description())
print("Total Cost: $", my_drink.get_cost())// Standard OO languages (like Java) require shared interfaces:
// interface Coffee { double getCost(); }
// class SimpleCoffee implements Coffee { ... }
// class MilkDecorator implements Coffee { ... }
// Python's duck typing allows dynamic composition without interfaces.Verdict et résumé
Utilisez les décorateurs Python (@decorator) lorsque vous souhaitez appliquer des préoccupations transversales (telles que la journalisation, la synchronisation, l'authentification, la mise en cache ou la validation des entrées) aux fonctions ou aux itinéraires de manière uniforme dans votre application.
Utilisez le modèle de conception Decorator lorsque vous devez attacher ou détacher des comportements d'instances d'objet individuelles de manière dynamique au moment de l'exécution, en particulier lorsque vous combinez plusieurs classes wrapper facultatives dans des séquences arbitraires.
Foire aux questions
Pourquoi la page Wikipédia indique-t-elle que les décorateurs Python ne sont pas le modèle de décorateur ?
Parce que les décorateurs Python standard encapsulent les fonctions et les définitions de classe au moment de la compilation/définition, affectant toutes les instances de cette fonction. Le modèle de conception classique encapsule dynamiquement les instances d’objet individuelles au moment de l’exécution.
Le modèle GoF Decorator est-il utile en Python ?
Oui, mais le typage canard de Python le rend beaucoup plus simple à implémenter que dans les langages typés statiquement comme Java ou C++, puisque les décorateurs n'ont pas besoin d'hériter d'une interface de base formelle.
Autres comparaisons
Ressources Python recommandées
Développez vos connaissances avec des didacticiels interactifs, des aide-mémoire et des comparaisons de codes associés.
Décorateurs Python
Apprenez les décorateurs Python pour modifier le comportement des fonctions de manière dynamique. Comprendre les fonctions wrapper, la syntaxe @ et la gestion des arguments dans les décorateurs.
Comment créer et utiliser des décorateurs en Python
Apprenez à écrire et appliquer des décorateurs en Python. Maîtrisez les fonctions d'encapsulation, modifiez le comportement, gérez les arguments et préservez les métadonnées avec des encapsulations.
Aide-mémoire sur les modèles Python Regex (re module)
Guide de référence pour les expressions régulières Python. Apprenez les modèles de correspondance, de recherche, de recherche, de sous et d'expression régulière essentiels.