Объясните принцип работы сборщика мусора (garbage collector) в Python.

«Объясните принцип работы сборщика мусора (garbage collector) в Python.» — вопрос из категории Python, который задают на 26% собеседований Data Scientist / ML Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В Python за автоматическое управление памятью отвечает сборщик мусора (GC). Он работает на основе комбинации подсчета ссылок (reference counting) и циклического сборщика мусора (generational cyclic GC).

  1. Подсчет ссылок: Каждый объект имеет счетчик, который увеличивается при создании новой ссылки на него и уменьшается при удалении ссылки. Когда счетчик достигает нуля, память объекта немедленно освобождается.

    a = []  # Создается список, счетчик ссылок = 1
    b = a   # b ссылается на тот же список, счетчик = 2
    del a   # Удаляется ссылка 'a', счетчик = 1
    b = None # Удаляется ссылка 'b', счетчик = 0 -> память списка освобождается
  2. Циклический сборщик мусора (Generational GC): Он нужен для обнаружения и удаления циклических ссылок, которые не могут быть обработаны простым подсчетом.

    # Пример циклической ссылки
    list1 = []
    list2 = []
    list1.append(list2) # list1 ссылается на list2
    list2.append(list1) # list2 ссылается на list1 -> цикл
    # Даже если удалить внешние переменные, счетчики ссылок не обнулятся.

    GC делит объекты на три поколения (0, 1, 2). Новые объекты попадают в поколение 0. Если объект переживает сборку мусора в своем поколении, он перемещается в следующее, более старое поколение. Сборки мусора для поколения 0 происходят чаще, чем для поколения 1 и 2, что оптимизирует работу, так как большинство объектов становятся мусором быстро.

Можно вручную управлять GC через модуль gc:

import gc
# Отключаем циклический GC (осторожно, только для узких оптимизаций)
gc.disable()
# ... критический по производительности код ...
gc.enable()
# Принудительный запуск полной сборки
collected = gc.collect()
print(f"Освобождено объектов: {collected}")