Как ответить
__slots__ — это механизм, который позволяет явно задать атрибуты экземпляра класса, заменяя стандартный словарь __dict__ на более компактную структуру. Основная цель — экономия памяти и ускорение доступа к атрибутам за счёт фиксированной схемы хранения.
Когда ты определяешь __slots__ как кортеж или список имён атрибутов, Python не создаёт для экземпляров __dict__ и __weakref__ (если они не указаны в __slots__). Вместо этого атрибуты хранятся в дескрипторах — каждое имя получает позицию внутри массива C-структуры. Это сильно сокращает накладные расходы: словарь экземпляра занимает ~56 байт пустой, плюс память на сами хэш-таблицы. С __slots__ для, скажем, класса с двумя атрибутами каждый экземпляр будет весить около 24 байт вместо 56+. Разница становится заметной на тысячах или миллионах объектов.
Обратная сторона — гибкость теряется: нельзя добавлять новые атрибуты динамически (кроме случаев, когда __dict__ явно включён в __slots__). Также нельзя наследовать __slots__ «автоматически» — если подкласс не объявит свои __slots__, он вернётся к __dict__. При множественном наследовании нужно помнить про коллизии имён (что один слот может быть объявлен в нескольких родителях).
Пример использования:
class Point:
__slots__ = ('x', 'y')
def __init__(self, x, y):
self.x = x
self.y = y
p = Point(1, 2)
print(p.x) # 1
# p.z = 3 # AttributeError: 'Point' object has no attribute 'z'
print(p.__slots__) # ('x', 'y')
# print(p.__dict__) # AttributeErrorЯ использую __slots__ в проектах, где есть множество мелких объектов — например, узлы графа, точки в 3D, лёгкие DTO для сериализации. Но не стоит применять «на всякий случай»: если класс всё равно будет иметь __dict__ (из-за наследования или явного включения), выигрыш исчезает. Лучше профилировать.