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

100 lines
3.0 KiB
Org Mode
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

:PROPERTIES:
:ID: 05864d6a-7a05-4c11-af14-4faebfdd1926
:mtime: 20220527182207
:ctime: 20220527165926
:END:
#+title: 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__~ :
#+BEGIN_SRC python :results output
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__)}')
#+END_SRC
#+RESULTS:
: '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.
#+BEGIN_SRC python :results output
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__)}')
#+END_SRC
#+RESULTS:
: '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).
* Références
* [[https://www.invivoo.com/les-slots-une-optimisation-meconnue/][Les slots, une optimisation méconnue - Invivoo]]