Para soportar la asignación de atributos arbitrarios, un objeto necesita un __dict__
: un dictado asociado con el objeto, donde se pueden almacenar atributos arbitrarios. De lo contrario, no hay ningún lugar donde colocar nuevos atributos.
Una instancia de object
qué no llevar un __dict__
- si lo hiciera, antes de que el problema de la dependencia circular horribles (ya que dict
, como casi todo lo demás, hereda de object
;-), esto sería cargar a cada objeto en Python con un diccionario, lo que significaría una sobrecarga de muchos bytes por objeto que actualmente no tiene o necesita un dict (esencialmente, todos los objetos que no tienen atributos asignables arbitrariamente no tienen o necesitan un dict).
Por ejemplo, usando el excelente pympler
proyecto (puede obtenerlo a través de svn desde aquí ), podemos hacer algunas medidas ...:
>>> from pympler import asizeof
>>> asizeof.asizeof({})
144
>>> asizeof.asizeof(23)
16
No querría que cada uno int
ocupe 144 bytes en lugar de solo 16, ¿verdad? -)
Ahora, cuando haces una clase (heredando de lo que sea), las cosas cambian ...:
>>> class dint(int): pass
...
>>> asizeof.asizeof(dint(23))
184
... el __dict__
se añade ahora (además, un poco más sobrecarga) - por lo que una dint
instancia puede tener atributos arbitrarios, pero que pagar un costo de un espacio para que la flexibilidad.
Entonces, ¿qué pasaría si quisieras int
s con solo un atributo adicional foobar
...? Es una necesidad poco común, pero Python ofrece un mecanismo especial para ese propósito ...
>>> class fint(int):
... __slots__ = 'foobar',
... def __init__(self, x): self.foobar=x+100
...
>>> asizeof.asizeof(fint(23))
80
... no es bastante tan pequeño como una int
, que importa! (o incluso los dos int
s, uno el self
y otro el self.foobar
- el segundo se puede reasignar), pero seguramente mucho mejor que a dint
.
Cuando la clase tiene el __slots__
atributo especial (una secuencia de cadenas), entonces la class
declaración (más precisamente, la metaclase predeterminada type
) no equipa cada instancia de esa clase con un __dict__
(y por lo tanto la capacidad de tener atributos arbitrarios), solo un finito , conjunto rígido de "ranuras" (básicamente lugares que pueden contener una referencia a algún objeto) con los nombres de pila.
A cambio de la flexibilidad perdida, se obtiene una gran cantidad de bytes por ejemplo (probablemente significativas sólo si tiene millones y millones de casos gallivanting alrededor, pero, no son casos de uso para eso).
object
tipo es inmutable y no se pueden agregar nuevos atributos? Esto parece que tendría más sentido.