Um die Zuweisung beliebiger Attribute zu unterstützen, benötigt ein Objekt Folgendes __dict__
: ein dem Objekt zugeordnetes Diktat, in dem beliebige Attribute gespeichert werden können. Ansonsten gibt es nirgendwo zu setzen neue Attribute.
Eine Instanz von object
trägt nicht ein __dict__
- wenn ja, vor dem schrecklichen Problem der zirkulären Abhängigkeit (da dict
, wie fast alles andere, von object
;-) erbt , würde dies jedes Objekt in Python mit einem Diktat satteln , was einen Overhead bedeuten würde von vielen Bytes pro Objekt, die derzeit kein Diktat haben oder benötigen (im Wesentlichen haben oder benötigen alle Objekte, die keine willkürlich zuweisbaren Attribute haben, kein Diktat).
Mit dem hervorragenden pympler
Projekt (das Sie hier über svn erhalten können ) können wir beispielsweise einige Messungen durchführen ...:
>>> from pympler import asizeof
>>> asizeof.asizeof({})
144
>>> asizeof.asizeof(23)
16
Sie möchten nicht, dass jeder int
144 Bytes statt nur 16 Bytes belegt, oder? -)
Wenn Sie nun eine Klasse erstellen (von was auch immer erben), ändern sich die Dinge ...:
>>> class dint(int): pass
...
>>> asizeof.asizeof(dint(23))
184
... das __dict__
wird jetzt hinzugefügt (plus etwas mehr Overhead) - so kann eine dint
Instanz beliebige Attribute haben, aber Sie zahlen ziemlich viel Platz für diese Flexibilität.
Was wäre, wenn Sie int
s mit nur einem zusätzlichen Attribut wollten foobar
...? Es ist eine seltene Notwendigkeit, aber Python bietet einen speziellen Mechanismus für diesen Zweck ...
>>> class fint(int):
... __slots__ = 'foobar',
... def __init__(self, x): self.foobar=x+100
...
>>> asizeof.asizeof(fint(23))
80
... nicht ganz so klein wie ein int
, wohlgemerkt! (oder sogar die zwei int
s, eins das self
und eins das self.foobar
- das zweite kann neu zugewiesen werden), aber sicherlich viel besser als a dint
.
Wenn die Klasse das __slots__
spezielle Attribut (eine Folge von Zeichenfolgen) hat, rüstet die class
Anweisung (genauer gesagt die Standard-Metaklasse type
) nicht jede Instanz dieser Klasse mit einem __dict__
(und daher der Fähigkeit, beliebige Attribute zu haben) aus, sondern nur mit einem Endlichen , starrer Satz von "Schlitzen" (im Grunde Orte, die jeweils einen Verweis auf ein Objekt enthalten können) mit den angegebenen Namen.
Als Gegenleistung für die verlorene Flexibilität erhalten Sie eine Menge Bytes pro Instanz (wahrscheinlich nur dann sinnvoll, wenn Sie zig Instanzen haben, die herum galoppieren, aber es gibt Anwendungsfälle dafür).
object
Typ ist unveränderlich und neue Attribute können nicht hinzugefügt werden? Dies scheint am sinnvollsten zu sein.