Как устроено управление памятью в Python
Что проверяют
Знаете ли вы про подсчёт ссылок плюс сборщик циклов и понимаете ли, что память не всегда возвращается операционной системе.
Как отвечать
Основной механизм это подсчёт ссылок. У каждого объекта есть счётчик; он растёт при появлении новой ссылки и падает при её исчезновении. Дошёл до нуля, объект уничтожается немедленно, детерминированно.
Подсчёт не справляется с циклами: два объекта ссылаются друг на друга, счётчики не нули, а снаружи они недостижимы. Для этого есть поколенческий сборщик циклов (модуль gc): три поколения, молодые проверяются часто, дожившие реже.
Ниже уровнем работает аллокатор: объекты мельче 512 байт обслуживает pymalloc через арены, пулы и блоки, крупные уходят в системный аллокатор. Отсюда важное следствие: освобождение объекта не означает возврата памяти операционной системе. Арена возвращается, только если полностью пуста, поэтому потребление процесса после пиковой нагрузки часто не снижается, и это не утечка.
Ещё стоит назвать оптимизации: маленькие целые числа и короткие строки кэшируются и переиспользуются, поэтому is для них иногда даёт неожиданный результат; __slots__ убирает словарь атрибутов и заметно экономит на миллионах объектов; weakref позволяет ссылаться, не удерживая.
Что считается утечкой на практике: живая ссылка в глобальном списке или кэше, незакрытые ресурсы, ссылки в замыканиях и в трассировке исключения. Ищут через tracemalloc и objgraph.
Где спотыкаются
Говорят только про сборщик мусора, забывая, что почти всё освобождает подсчёт ссылок.
Считают, что del удаляет объект, а не имя.
Уверены, что после освобождения память сразу возвращается системе.
Не знают про __slots__ и удивляются расходу на простых объектах.