Pour prendre en charge l'attribution arbitraire d'attributs, un objet a besoin d'un __dict__: un dict associé à l'objet, où des attributs arbitraires peuvent être stockés. Sinon, il n'y a nulle part où mettre de nouveaux attributs.
Une instance de objectne transporte pas un __dict__- si c'était le cas, avant l'horrible problème de dépendance circulaire (puisque dict, comme presque tout le reste, hérite de object;-), cela mettrait en selle chaque objet en Python avec un dict, ce qui signifierait une surcharge de nombreux octets par objet qui n'a actuellement pas ou n'a pas besoin d'un dict (essentiellement, tous les objets qui n'ont pas d'attributs assignables arbitrairement n'ont pas ou n'ont pas besoin d'un dict).
Par exemple, en utilisant l'excellent pymplerprojet (vous pouvez l'obtenir via svn à partir d' ici ), nous pouvons faire quelques mesures ...:
>>> from pympler import asizeof
>>> asizeof.asizeof({})
144
>>> asizeof.asizeof(23)
16
Vous ne voudriez pas que chacun intprenne 144 octets au lieu de seulement 16, non? -)
Maintenant, quand vous créez une classe (héritant de quoi que ce soit), les choses changent ...:
>>> class dint(int): pass
...
>>> asizeof.asizeof(dint(23))
184
... le __dict__ est maintenant ajouté (en plus, un peu plus de frais généraux) - une dintinstance peut donc avoir des attributs arbitraires, mais vous payez un coût d'espace assez élevé pour cette flexibilité.
Et si vous vouliez des ints avec un seul attribut supplémentaire foobar...? C'est un besoin rare, mais Python offre un mécanisme spécial à cet effet ...
>>> class fint(int):
... __slots__ = 'foobar',
... def __init__(self, x): self.foobar=x+100
...
>>> asizeof.asizeof(fint(23))
80
...ne pas tout à fait aussi petit comme intvous l' esprit! (ou même les deux ints, un le selfet un le self.foobar- le second peut être réaffecté), mais sûrement beaucoup mieux qu'un dint.
Lorsque la classe a le __slots__ attribut spécial (une séquence de chaînes), alors l' classinstruction (plus précisément, la métaclasse par défaut, type) n'équipe pas chaque instance de cette classe avec un __dict__(et donc la possibilité d'avoir des attributs arbitraires), juste un fini , ensemble rigide de "slots" (essentiellement des endroits qui peuvent chacun contenir une référence à un objet) avec les noms donnés.
En échange de la flexibilité perdue, vous gagnez beaucoup d'octets par instance (probablement significatif uniquement si vous avez des millions d'instances qui circulent, mais il existe des cas d'utilisation pour cela).
objecttype est immuable et de nouveaux attributs ne peuvent pas être ajoutés? Cela semble être le plus logique.