ProgrammationDéveloppeur Backend

Qu'est-ce que les décorateurs de classes en Python ? Comment peuvent-ils modifier ou compléter la fonctionnalité des classes ? Donnez un exemple et parlez des nuances possibles.

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Un décorateur de classe est une fonction qui prend une classe comme argument et renvoie soit une classe modifiée, soit une classe complètement nouvelle. Avec eux, il est possible d'ajouter dynamiquement des méthodes, de modifier le comportement des méthodes existantes ou même de renvoyer une sous-classe qui étend la fonctionnalité de la classe originale.

Exemple simple de décorateur de classe :

def add_repr(cls): def __repr__(self): return f'<{cls.__name__}: {self.__dict__}>' cls.__repr__ = __repr__ return cls @add_repr class Point: def __init__(self, x, y): self.x = x self.y = y p = Point(3, 4) print(p) # <Point: {'x': 3, 'y': 4}>
  • Le décorateur add_repr ajoute dynamiquement la méthode __repr__ à toutes les classes auxquelles il est appliqué.

Nuances :

  • Les décorateurs de classes peuvent renvoyer non seulement des emboîtements dans la classe, mais aussi des classes complètement enveloppées (par exemple, des classes proxy ou des héritiers).
  • Des erreurs peuvent survenir si le décorateur ne prend pas en charge les arguments *args et **kwargs, utilisés lors de la création d'instances de la classe.

Question piégeuse.

Que se passe-t-il si l’on applique deux décorateurs de classe les uns après les autres ? L'ordre de leur application est-il toujours évident ?

Réponse :

Les décorateurs sont appliqués "de bas en haut" : d'abord le décorateur directement au-dessus de la déclaration de classe, puis le suivant au-dessus, etc. L'ordre est TRÈS IMPORTANT, car le résultat du premier décorateur est passé au second, et ainsi de suite.

@dec1 @dec2 class Test: ... # Équivalent à : # Test = dec1(dec2(Test))

Exemples d'erreurs réelles dues à une méconnaissance des subtilités du sujet.


Histoire

Dans une application e-commerce, il était souhaité de journaliser les méthodes de classe, mais par erreur, un objet incorrect a été retourné par le décorateur, et les méthodes ont perdu leur propriété de classe, ce qui a entraîné des problèmes d'héritage, brisant le fonctionnement du modèle.


Histoire

Dans un projet d'autogénération de nouvelles méthodes, un décorateur ajoutant a été utilisé, mais super() a été oublié lors du retour d'une sous-classe. En conséquence, la hiérarchie et la MRO ont été rompues, entraînant des appels non fonctionnels de la classe de base dans les sous-classes.


Histoire

Dans un pipeline de données, on a tenté d'enrouler des classes avec plusieurs décorateurs (journaliseur, traceur de modifications), mais en raison d'un ordre incorrect d'application, un conflit de noms de méthodes a surgi, entraînant des bugs en production en raison de méthodes "perdues".