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 object
non 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 pympler
progetto (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 int
occupasse 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 dint
un'istanza può avere attributi arbitrari, ma per questa flessibilità paghi un costo abbastanza elevato.
E se volessi messaggi int
con 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 self
e 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' class
istruzione (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).
object
tipo è immutabile e non è possibile aggiungere nuovi attributi? Sembra che abbia più senso.