Для підтримки довільного присвоєння атрибутів об'єкту потрібно __dict__
: dict, пов'язаний з об'єктом, де можна зберігати довільні атрибути. В іншому випадку нікуди поставити нові атрибути.
Примірник object
зовсім НЕ носити з собою __dict__
- якщо це так, перед жахливою кругової завданням залежності (так dict
, як і більшість решти, успадковується від object
;-), це було б осідлати кожен об'єкт в Python з Dict, що означало б накладні витрати з багатьох байт на об'єкт , який в даний час не має або НЕ потребує 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, один the self
та one the self.foobar
- другий може бути перепризначений), але, безумовно, набагато кращий ніжdint
.
Коли клас має __slots__
спеціальний атрибут (послідовність рядків), тоді class
оператор (точніше, метаклас за замовчуванням, type
) робить НЕ оснащувати кожен екземпляр цього класу з __dict__
(і , отже , можливістю мати довільні атрибути), тільки кінцевий , жорсткий набір "слотів" (в основному місця, кожна з яких може містити одне посилання на якийсь об'єкт) із заданими іменами.
В обмін на втрачену гнучкість ви отримуєте багато байтів на екземпляр (можливо, значущий лише у тому випадку, якщо навколо вас мільйони екземплярів, які галівантують, але для цього існують випадки використання).
object
тип незмінний, і нові атрибути не можна додавати? Здається, це мало би найбільший сенс.