Quel est le but de __slots__
en Python - notamment en ce qui concerne les cas où je souhaite l'utiliser et ceux où je ne le souhaite pas ?
Réponses
Trop de publicités?Citation : Jacob Hallen :
L'utilisation appropriée de
__slots__
est d'économiser de l'espace dans les objets. Au lieu d'avoir un dict dynamique qui permet d'ajouter des attributs aux objets à tout moment, il y a une structure statique qui ne permet pas d'ajouts après la création. [Cette utilisation de__slots__
élimine la surcharge d'un dict pour chaque objet]. Bien que ce soit parfois une optimisation utile, elle serait complètement complètement inutile si l'interpréteur Python était suffisamment dynamique pour ne pour n'avoir besoin du dict que lorsqu'il y a effectivement des ajouts à l'objet.Malheureusement, il y a un effet secondaire aux machines à sous. Ils modifient le comportement des des objets qui ont des slots d'une manière qui peut être abusée par les maniaques du contrôle et les fanatiques du typage statique. C'est mauvais, parce que les maniaques du contrôle devraient contrôle devraient abuser des métaclasses et les fanatiques du typage statique devraient abuser des décorateurs. puisqu'en Python, il ne devrait y avoir qu'une seule façon évidente de faire quelque chose.
Rendre CPython suffisamment intelligent pour gérer l'économie d'espace sans
__slots__
est un grand C'est probablement la raison pour laquelle elle ne figure pas (encore) sur la liste des modifications à apporter à P3k.
Vous devez utiliser __slots__
si vous avez l'intention d'instancier beaucoup (des centaines, des milliers) d'objets de la même classe. __slots__
n'existe que comme outil d'optimisation de la mémoire.
Il est fortement déconseillé d'utiliser __slots__
pour contraindre la création d'attributs.
Décapage des objets avec __slots__
ne fonctionnera pas avec le protocole pickle par défaut (le plus ancien) ; il est nécessaire de spécifier une version plus récente.
Certaines autres fonctionnalités d'introspection de python peuvent également être affectées.
Chaque objet python possède un __dict__
qui est un dictionnaire contenant tous les autres attributs. Par exemple, lorsque vous tapez self.attr
python est en train de faire self.__dict__['attr']
. Comme vous pouvez l'imaginer, l'utilisation d'un dictionnaire pour stocker les attributs prend un peu plus de place et de temps pour y accéder.
Cependant, lorsque vous utilisez __slots__
tout objet créé pour cette classe n'aura pas d'objet de type __dict__
attribut. Au lieu de cela, tous les accès aux attributs se font directement via des pointeurs.
Ainsi, si vous voulez une structure de type C plutôt qu'une classe à part entière, vous pouvez utiliser __slots__
pour compacter la taille des objets et réduire le temps d'accès aux attributs. Un bon exemple est une classe Point contenant les attributs x & y. Si vous avez beaucoup de points, vous pouvez essayer d'utiliser __slots__
afin de conserver un peu de mémoire.
Les slots sont très utiles pour les appels de bibliothèque afin d'éliminer le "named method dispatch" lors des appels de fonction. Ceci est mentionné dans le manuel SWIG documentation . Pour les bibliothèques à haute performance qui veulent réduire la surcharge des fonctions couramment appelées, l'utilisation des slots est beaucoup plus rapide.
Ceci n'est peut-être pas directement lié à la question de l'OP. Il est davantage lié à la construction d'extensions qu'à l'utilisation de l'outil de gestion de l'environnement. Machines à sous sur un objet. Mais cela permet de compléter l'image de l'utilisation des slots et de certains des raisonnements qui les sous-tendent.
Vous n'avez - essentiellement - aucune utilité pour __slots__
.
Pour le moment où vous pensez que vous pourriez avoir besoin __slots__
vous voulez en fait utiliser Léger o Poids plume les modèles de conception. Il s'agit de cas où vous ne souhaitez plus utiliser des objets purement Python. Au lieu de cela, vous voulez une enveloppe de type objet Python autour d'un tableau, d'une structure ou d'un tableau numpy.
class Flyweight(object):
def get(self, theData, index):
return theData[index]
def set(self, theData, index, value):
theData[index]= value
Le wrapper de type classe n'a pas d'attributs - il fournit simplement des méthodes qui agissent sur les données sous-jacentes. Les méthodes peuvent être réduites à des méthodes de classe. En effet, il pourrait être réduit à de simples fonctions opérant sur le tableau de données sous-jacent.