3.0 KiB
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 d’une classe mère s’ajoutent à ceux de la classe fille,
- Il ne peut exister qu’une 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).