0Pricing
Python Academy · Leçon

Écrire des décorateurs personnalisés

Créez des décorateurs avec des fonctions d’encapsulation et functools.wraps.

Écrire des décorateurs personnalisés est une leçon Python Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Python Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Python Academy comprend 4 leçons au total.

Introduction

Les décorateurs sont des fonctions qui enveloppent d’autres fonctions et ajoutent un comportement avant ou après leur exécution, sans modifier la fonction originale.

Qu’est-ce qu’un décorateur ?

@decorator placé au-dessus d’une fonction est un sucre syntaxique pour : func = decorator(func). Le décorateur reçoit la fonction et renvoie une fonction enveloppe.
def shout(func):
    def wrapper(*a, **kw):
        result = func(*a, **kw)
        return str(result).upper()
    return wrapper
@shout
def greet(name): return f'hello {name}'
print(greet('Alice'))

Le modèle de fonction enveloppe

La fonction enveloppe possède la même signature que l’originale. Elle appelle l’originale à l’intérieur et ajoute un comportement autour de cet appel.
def timer(func):
    import time
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        print(f'{func.__name__} took {time.time()-start:.4f}s')
        return result
    return wrapper
@timer
def slow(): import time; time.sleep(0.01)
slow()

functools.wraps

@wraps(func) appliqué à la fonction enveloppe préserve le __name__, le __doc__ et les __annotations__ de la fonction originale.
from functools import wraps
def log(func):
    @wraps(func)
    def wrapper(*a, **kw):
        print(f'calling {func.__name__}')
        return func(*a, **kw)
    return wrapper
@log
def add(a, b): return a + b
print(add.__name__)
add(1, 2)

Décorateur avec arguments

Un décorateur avec arguments nécessite un niveau d’enveloppement supplémentaire : une fonction fabrique qui reçoit les arguments et renvoie le décorateur.
def repeat(n):
    def decorator(func):
        from functools import wraps
        @wraps(func)
        def wrapper(*a, **kw):
            for _ in range(n): func(*a, **kw)
        return wrapper
    return decorator
@repeat(3)
def hi(): print('hi')
hi()

Empilement de décorateurs

Les décorateurs multiples s’empilent de bas en haut : @d2 @d1 signifie func = d2(d1(func)). Le décorateur extérieur (celui du haut) s’exécute en dernier.
def bold(f):
    from functools import wraps
    @wraps(f)
    def w(*a,**k): return '<b>' + f(*a,**k) + '</b>'
    return w
def italic(f):
    from functools import wraps
    @wraps(f)
    def w(*a,**k): return '<i>' + f(*a,**k) + '</i>'
    return w
@bold
@italic
def text(): return 'hello'
print(text())

Décorateur fondé sur une classe

Une classe qui possède __call__ peut servir de décorateur. Elle conserve un état entre les appels.
class Counter:
    def __init__(self, func): self.func,self.count=func,0
    def __call__(self, *a, **kw):
        self.count+=1
        return self.func(*a, **kw)
@Counter
def greet(name): return f'hi {name}'
greet('Alice'); greet('Bob')
print(greet.count)

Décorateur de mémoïsation

Mettez en cache les résultats précédents pour éviter de recalculer : if args in cache: return cache[args]. functools.lru_cache fait cela automatiquement.
from functools import lru_cache
@lru_cache(maxsize=None)
def fib(n):
    if n < 2: return n
    return fib(n-1) + fib(n-2)
print(fib(30))

Décorateur d’autorisation

Les décorateurs sont courants pour le contrôle d’accès : vérifiez que l’utilisateur est connecté avant d’exécuter la fonction.
def requires_auth(func):
    from functools import wraps
    @wraps(func)
    def wrapper(user, *a, **kw):
        if not user.get('authenticated'):
            raise PermissionError('Not authenticated')
        return func(user, *a, **kw)
    return wrapper
@requires_auth
def dashboard(user): return 'Welcome!'
try: dashboard({'authenticated': False})
except PermissionError as e: print(e)

Décorateur de nouvelle tentative

Enveloppez une fonction pour réessayer en cas d’échec : for _ in range(retries): try: return func() except Exception: pass
import random
from functools import wraps
def retry(times=3):
    def dec(func):
        @wraps(func)
        def wrapper(*a, **kw):
            for i in range(times):
                try: return func(*a, **kw)
                except Exception as e:
                    if i==times-1: raise
        return wrapper
    return dec
@retry(3)
def flaky():
    if random.random()<0.7: raise ValueError
    return 'ok'
try: print(flaky())
except ValueError: print('failed')

Bonnes pratiques pour les décorateurs

Utilisez toujours @functools.wraps. Limitez chaque décorateur à une seule responsabilité. Documentez ce qu’il ajoute. Testez le décorateur séparément de la fonction décorée.
from functools import wraps
def validate_positive(func):
    @wraps(func)
    def wrapper(x, *a, **kw):
        if x <= 0: raise ValueError(f'{x} must be positive')
        return func(x, *a, **kw)
    return wrapper
@validate_positive
def sqrt(x): return x**0.5
print(sqrt(9))

Vérification rapide

Que fait @functools.wraps(func) lorsqu’il est appliqué à une fonction enveloppe ?

Récapitulatif

Décorateurs : func = decorator(func). Utilisez wrapper(*args, **kwargs). @wraps préserve les métadonnées. Les décorateurs paramétrés ajoutent un niveau supplémentaire. Empilez-les avec plusieurs @decorators.

Continuez

Vos progrès sont excellents ! Continuez pour maîtriser le prochain concept.

Questions Fréquemment Posées

La leçon « Écrire des décorateurs personnalisés » est-elle gratuite ?

Oui — le texte complet de « Écrire des décorateurs personnalisés » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Python Academy, passe à CoddyKit PRO. Le cours Python Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Écrire des décorateurs personnalisés » ?

Créez des décorateurs avec des fonctions d’encapsulation et functools.wraps. Tu pratiques Python Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Python Academy ?

Aucune expérience préalable n'est requise. Python Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.

Combien de temps prend la leçon « Écrire des décorateurs personnalisés » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Python Academy ?

Oui. Chaque leçon Python Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Les fonctions comme objets de première classe
  2. Écrire des décorateurs personnalisés
  3. Le décorateur @property
  4. @classmethod et @staticmethod
← Retour à Python Academy