Куча (heap) - все объекты (числа, строки, списки, экземпляры классов и т.д.) живут в куче — области памяти, управляемой интерпретатором.
Стек вызовов - для каждой вызываемой функции создаётся фрейм на стеке: локальные переменные, аргументы, ссылки на объекты в куче.
Важный момент: локальная переменная x — это не сам объект, а ссылка на него.
Подсчёт ссылок + GC
У объекта есть счётчик ссылок; когда он падает до нуля, объект сразу освобождается, память возвращается аллокатору. Для циклов ссылок поверх этого работает генерационный сборщик мусора.
Модель «всё — объект»
Даже функции, классы и модули — объекты в куче, на которые ссылаются имена в пространствах имён. Ответ для middle‑специалиста обычно ожидают на уровне: «объекты в куче, ссылки на них в стеке, управление памятью через подсчёт ссылок плюс GC для циклов».
Что делает __slots__
По умолчанию у каждого экземпляра пользовательского класса есть словарь __dict__, где хранятся его атрибуты:
class User:
def __init__(self, name, age):
self.name = name
self.age = age
u = User("Ann", 30)
print(u.__dict__) # {'name': 'Ann', 'age': 30}Это даёт гибкость (можно в любой момент дописать u.foo = 1), но у словаря есть цена: память и скорость доступа. Если в классе объявить __slots__, Python не будет создавать __dict__ для экземпляров, а вместо этого выделит фиксированную структуру под указанные атрибуты:
class User:
__slots__ = ("name", "age")
def __init__(self, name, age):
self.name = name
self.age = age
u = User("Ann", 30)
# u.__dict__ -> AttributeError: 'User' object has no attribute '__dict__'Эффекты коллекции __slots__
Экономия памяти. Для большого количества однотипных объектов (например, миллионов DTO или ORM‑моделей) экономия может составлять 20–50% на экземпляр.
Более быстрый доступ к атрибутам. Доступ идёт по смещению в фиксированной структуре, а не через словарь → обычно даёт прирост 10–20% к скорости доступа к полям.
Запрет произвольных атрибутов. Нельзя написать
u.foo = 1, еслиfooне объявлен в__slots__— будетAttributeError. Это иногда используют как способ ограничить интерфейс объектов и ловить опечатки вместо тихого создания нового поля.
Ограничения и нюансы __slots__
На собеседовании хорошо упомянуть не только плюсы, но и ограничения:
__slots__не наследуются автоматически как ожидают новички — при сложной иерархии классов нужно аккуратно их проектировать, учитывая, как объединяются слоты базовых и дочерних классов.Экземпляр класса с
__slots__по умолчанию не имеет__dict__и__weakref__; если они нужны, их нужно явно добавить в__slots__.__slots__разумно применять там, где:
- очень много однотипных объектов (модели, ноды AST, структуры данных);
- набор полей стабилен и заранее известен;
- важны память и скорость доступа.
В обычном бизнес‑коде для нескольких десятков объектов выгода минимальна, а гибкость теряется.
Модель памяти Python: объекты живут в куче, переменные — это ссылки на них в стеке и словарях пространств имён, память управляется подсчётом ссылок и генерационным GC для циклических ссылок. __slots__ — это настройка класса, которая отключает словарь атрибутов __dict__ у экземпляров и заменяет его фиксированной структурой с заранее объявленными полями. Это уменьшает память на экземпляр и ускоряет доступ к атрибутам, но запрещает динамически добавлять новые поля и требует аккуратности при наследовании.