Для поддержки произвольного присвоения атрибута объекту требуется __dict__
: дикт, связанный с объектом, где могут храниться произвольные атрибуты. Иначе некуда поставить новых атрибутов.
Экземпляр object
не не несет __dict__
- если это так, до ужасной проблемы круговой зависимости (поскольку dict
, как и большинство всего остального, наследуется от object
;-), это оседлало бы каждый объект в Python с dict, что означало бы издержки много байтов на объект, который в настоящее время не имеет или не нуждается в dict (по существу все объекты, которые не имеют произвольно назначаемых атрибутов, не имеют или нуждаются в диктовке).
Например, используя отличный проект pympler
(вы можете получить его через svn из здесь ), мы можем сделать некоторые измерения ...:
>>> from pympler import asizeof
>>> asizeof.asizeof({})
144
>>> asizeof.asizeof(23)
16
Вы бы не хотели, чтобы каждые int
занимали 144 байта вместо 16, верно? -)
Теперь, когда вы создаете класс (унаследованный от чего бы то ни было), все меняется ...:
>>> class dint(int): pass
...
>>> asizeof.asizeof(dint(23))
184
... теперь добавлено __dict__
(плюс, немного больше накладных расходов) - так что экземпляр dint
может иметь произвольные атрибуты, но вы платите довольно много места за эту гибкость .
Так что, если вы хотите int
s только с одним дополнительным атрибутом foobar
...? Это редкая необходимость, но Python предлагает специальный механизм для этой цели ...
>>> class fint(int):
... __slots__ = 'foobar',
... def __init__(self, x): self.foobar=x+100
...
>>> asizeof.asizeof(fint(23))
80
... не совсем крошечный как int
, учтите! (или даже два int
s, один self
и один self.foobar
- второй можно переназначить), но, безусловно, намного лучше, чем dint
.
Если у класса есть специальный атрибут __slots__
(последовательность строк), тогда оператор class
(точнее, метакласс по умолчанию, type
) делает , а не , оснащая каждый экземпляр этот класс с __dict__
(и, следовательно, способностью иметь произвольные атрибуты), просто конечный, жесткий набор «слотов» (в основном это места, каждый из которых может содержать одну ссылку на некоторый объект) с заданными именами.
В обмен на потерянную гибкость вы получаете много байтов за каждый экземпляр (вероятно, значимый, только если у вас есть миллионы экземпляров, которые находятся вокруг, но есть вариантов использования для этого).