ProgrammationDéveloppeur Backend Python

Qu'est-ce que __slots__ dans les classes Python, à quoi servent-ils et quelles sont leurs limitations ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

__slots__ est un attribut spécial de la classe qui limite l'ensemble des attributs d'instance autorisés, économise de la mémoire et accélère l'accès aux attributs. L'utilisation de __slots__ est particulièrement pertinente pour un grand nombre d'objets similaires.

Contexte :

L'apparition de __slots__ est liée au fait que, par défaut, chaque instance d'un objet Python dispose d'un dictionnaire d'attributs (__dict__), ce qui est pratique mais coûteux en mémoire. Pour un million d'objets avec un petit ensemble de champs, un overhead significatif se produit.

Problème :

Les instances d'une classe ordinaire peuvent être étendues dynamiquement, ce qui est pratique mais inefficace. L'application de __slots__ limite l'ajout dynamique de nouveaux attributs, supprime le dictionnaire d'attributs de l'instance, économise de la mémoire et accélère l'accès.

Solution :

Décrivez la liste des champs autorisés dans l'attribut __slots__:

class Point: __slots__ = ('x', 'y') def __init__(self, x, y): self.x = x self.y = y p = Point(1, 2) p.z = 3 # AttributeError: l'objet 'Point' n'a pas d'attribut 'z'

Caractéristiques clés :

  • Économise de la mémoire en raison de l'absence de dict et weakref par défaut.
  • Définit un ensemble strict de champs autorisés.
  • Permet d'accélérer l'accès aux attributs grâce à des emplacements prédéfinis (pas de recherche dans le dict).

Questions pièges.

Peut-on créer une instance d'une classe avec slots et ensuite ajouter un attribut non présent dans la liste ?

Non. Lorsqu'on essaie d'ajouter un attribut absent de la liste slots, un AttributeError sera levé. Cela impose des limites à l'extensibilité de l'objet.

Peut-on hériter d'une classe avec slots et ajouter de nouveaux champs ?

Oui, mais chaque héritier doit déclarer ses propres slots. Dans ce cas, les slots parents et actuels sont combinés. Cependant, si on ne déclare pas slots dans l'héritier, le descendant retrouvera à nouveau dict !

Est-ce que slots fonctionne pour les types immuables ?

Oui, mais il faut mettre en œuvre des mesures supplémentaires pour rendre l'objet à slots immuable (par exemple, via property sans setter).

Erreurs typiques et anti-patrons

  • Ne pas déclarer slots dans la classe fille, ruinant l'efficacité mémoire.
  • S'attendre à ce que slots fonctionne en présence d'héritage multiple — des conflits et des erreurs peuvent survenir.
  • La tentative de sérialiser des objets avec des slots par des moyens standards est parfois difficile (par exemple, pickle nécessite dict).

Exemple de la vie

Cas négatif

Classe ordinaire pour un point :

class Point: def __init__(self, x, y): self.x = x self.y = y points = [Point(i, i) for i in range(1_000_000)]

Avantages :

  • Flexible — on peut ajouter n'importe quel attribut.
  • Compréhensible pour les débutants.

Inconvénients :

  • Le gestionnaire de tâches affiche une consommation de mémoire nettement surestimée (jusqu'à +20-30%).

Cas positif

Classe similaire, mais avec des slots :

class Point: __slots__ = ('x', 'y') def __init__(self, x, y): self.x = x self.y = y points = [Point(i, i) for i in range(1_000_000)]

Avantages :

  • Économie de mémoire allant jusqu'à 30 % sur des millions d'objets.
  • Accès plus rapide aux champs.

Inconvénients :

  • Les objets deviennent rigides : il n'est pas possible d'ajouter de nouveaux attributs à la volée.