Files
org-roamings/20220527165926-l_attribut_de_classe_slots.org
2022-06-04 12:57:39 +02:00

3.0 KiB
Raw Blame History

L'attribut de classe slots

Introduction

Par défaut, chaque objet possède l'attibut __dict__ stockant la liste de ses attributs sous forme de dict. Il est ainsi possible d'ajouter des attributs à un objet en dehors de la méthode __init__ :

from sys import getsizeof

class Dummy:

    def __init__(self, a: int, b: int) -> None:
        self.a = a
        self.b = b

dummy = Dummy(1, 2)
try:
    print(dummy.__slots__)
except AttributeError as e:
    print(e)

print(f'{dummy.__dict__=}')
    
dummy.c = 3
print(f'{dummy.__dict__=}')

print(f'{getsizeof(dummy) + getsizeof(dummy.__dict__)}')
'Dummy' object has no attribute '__slots__'
dummy.__dict__={'a': 1, 'b': 2}
dummy.__dict__={'a': 1, 'b': 2, 'c': 3}
152

L'utilisation d'un dict pour stocker les attributs de chaque objet permet cette souplesse mais a pour conséquence un usage mémoire qui pourrait être amélioré.

C'est pour cela que l'attributs __slots__ a été ajouté par Python3.

Usage

L'attribut de classe __slots__ est un tuple (taille inférieure à celle d'un dict mais imutable) contenant les attributs des instances.

from sys import getsizeof

class Dummy:

    __slots__ = ('a', 'b', 'c')

    def __init__(self, a: int, b: int) -> None:
        self.a = a
        self.b = b

dummy = Dummy(1, 2)
try:
    print(dummy.__dict__)
except AttributeError as e:
    print(e)

print(f'{dummy.__slots__=}')

dummy.c = 3
print(f'{dummy.__slots__=}')

try:
    dummy.d = 4
except AttributeError as e:
    print(e)

print(f'{getsizeof(dummy) + getsizeof(dummy.__slots__)}')
'Dummy' object has no attribute '__dict__'
dummy.__slots__=('a', 'b', 'c')
dummy.__slots__=('a', 'b', 'c')
'Dummy' object has no attribute 'd'
120

Avantages

L'usage de __slots__ permet de réduire la taille des objets. Néanmoins, l'écart se réduit plus le nombre d'attributs augmente. Les __slots__ sont donc utiles pour les classes ayant peu d'attributs et un grand nombre d'instances.

Le principal avantage de __slots__ réside dans les performances (environ 15% plus rapide), conséquence du temps d'accès plus rapide au contenu d'un tuple que d'un __dict__.

Inconvénients

L'absence de __dict__ empèche l'ajout dynamique d'attributs.

L'usage de __slots__ ajoute les règles suivantes quant à l'héritage :

  • Les slots dune classe mère sajoutent à ceux de la classe fille,
  • Il ne peut exister quune seule classe mère avec une séquence de slots non vide,
  • Si une des classes membres de l'arbre d'héritage ne déclare pas de __slots__, mêmes vides, les instances auront un attribut __dict__ (perte de l'optimisation).