Per supportare l'assegnazione di attributi arbitrari, un oggetto necessita di __dict__: un dict associato all'oggetto, in cui è possibile memorizzare attributi arbitrari. Altrimenti, non c'è nessun posto dove inserire nuovi attributi.
Un esempio di objectnon non portare in giro un __dict__- se così fosse, prima che il problema della dipendenza circolare orribile (poiché dict, come la maggior parte tutto il resto, eredita da object;-), ciò sella ogni oggetto in Python con un dizionario, il che significherebbe un overhead di molti byte per oggetto che attualmente non ha o necessita di un dict (essenzialmente, tutti gli oggetti che non hanno attributi assegnabili arbitrariamente non hanno o necessitano di un dict).
Ad esempio, utilizzando l'ottimo pymplerprogetto (puoi ottenerlo tramite svn da qui ), possiamo fare alcune misurazioni ...:
>>> from pympler import asizeof
>>> asizeof.asizeof({})
144
>>> asizeof.asizeof(23)
16
Non vorresti che ognuno intoccupasse 144 byte invece di solo 16, giusto? -)
Ora, quando crei una classe (ereditando da qualunque cosa), le cose cambiano ...:
>>> class dint(int): pass
...
>>> asizeof.asizeof(dint(23))
184
... ora __dict__ è stato aggiunto (in più, un po 'più di overhead) - quindi dintun'istanza può avere attributi arbitrari, ma per questa flessibilità paghi un costo abbastanza elevato.
E se volessi messaggi intcon un solo attributo in più foobar...? È una necessità rara, ma Python offre un meccanismo speciale per lo scopo ...
>>> class fint(int):
... __slots__ = 'foobar',
... def __init__(self, x): self.foobar=x+100
...
>>> asizeof.asizeof(fint(23))
80
... non è abbastanza piccola come una int, ti dispiacerebbe! (o anche i due int, uno il selfe uno il self.foobar- il secondo può essere riassegnato), ma sicuramente molto meglio di undint .
Quando la classe ha l' __slots__attributo speciale (una sequenza di stringhe), l' classistruzione (più precisamente, la metaclasse predefinita type) non fornisce a ogni istanza di quella classe un __dict__(e quindi la capacità di avere attributi arbitrari), solo un finito , insieme rigido di "slot" (fondamentalmente luoghi che possono contenere ciascuno un riferimento a un oggetto) con i nomi dati.
In cambio della flessibilità perduta, guadagni molti byte per istanza (probabilmente significativo solo se hai milioni di istanze in giro, ma ci sono casi d'uso per quello).
objecttipo è immutabile e non è possibile aggiungere nuovi attributi? Sembra che abbia più senso.