Para suportar a atribuição arbitrária de atributos, um objeto precisa de um __dict__
: um dict associado ao objeto, onde atributos arbitrários podem ser armazenados. Caso contrário, não há onde colocar novos atributos.
Uma instância de object
que não transportar cerca de um __dict__
- se isso acontecesse, antes que o problema da dependência circular horrível (desde dict
, como tudo o mais, herda de object
;-), isso sela cada objeto em Python com um dicionário, o que significaria uma sobrecarga de muitos bytes por objeto que atualmente não tem ou precisa de um dict (essencialmente, todos os objetos que não têm atributos atribuíveis arbitrariamente não têm ou precisam de um dict).
Por exemplo, usando o excelente pympler
projeto (você pode obtê-lo via svn a partir daqui ), podemos fazer algumas medições ...:
>>> from pympler import asizeof
>>> asizeof.asizeof({})
144
>>> asizeof.asizeof(23)
16
Você não gostaria que todos int
ocupassem 144 bytes em vez de apenas 16, certo? -)
Agora, quando você faz uma classe (herdando de qualquer coisa), as coisas mudam ...:
>>> class dint(int): pass
...
>>> asizeof.asizeof(dint(23))
184
... o agora __dict__
é adicionado (além de um pouco mais de sobrecarga) - portanto, uma dint
instância pode ter atributos arbitrários, mas você paga um custo de espaço considerável por essa flexibilidade.
E daí se você quisesse int
s com apenas um atributo extra foobar
...? É uma necessidade rara, mas Python oferece um mecanismo especial para o propósito ...
>>> class fint(int):
... __slots__ = 'foobar',
... def __init__(self, x): self.foobar=x+100
...
>>> asizeof.asizeof(fint(23))
80
... não muito pequenos como um int
, você mente! (ou mesmo os dois int
s, um o self
e um o self.foobar
- o segundo pode ser reatribuído), mas certamente muito melhor do que a dint
.
Quando a classe tem o __slots__
atributo especial (uma sequência de strings), a class
instrução (mais precisamente, a metaclasse padrão type
) não equipa cada instância dessa classe com um __dict__
(e, portanto, a capacidade de ter atributos arbitrários), apenas um , conjunto rígido de "slots" (basicamente lugares em que cada um pode conter uma referência a algum objeto) com os nomes dados.
Em troca da flexibilidade perdida, você ganha um monte de bytes por exemplo (provavelmente significativas somente se você tem zilhões de casos divertir ao redor, mas, não são casos de uso para isso).
object
tipo é imutável e novos atributos não podem ser adicionados? Parece que faria mais sentido.