Как работает сборщик мусора в python?

Сборщик мусора (garbage collector, GC) в Python отвечает за автоматическое управление памятью. Его задача — освобождать память, занятую неиспользуемыми объектами, чтобы она могла быть перераспределена для новых данных.

Давайте рассмотрим, как это работает, максимально подробно и с примерами.

🧠 Основы: как Python управляет памятью

Python использует управление памятью на основе подсчёта ссылок (reference counting) в сочетании с дополнительным сборщиком мусора для циклических ссылок.

🔷 1. Подсчёт ссылок (Reference Counting)

Каждый объект в Python хранит счётчик ссылок — количество других объектов или переменных, которые на него ссылаются.

  • Когда создаётся новая ссылка на объект — счётчик увеличивается.

  • Когда ссылка удаляется — счётчик уменьшается.

  • Если счётчик становится равным нулю, объект немедленно удаляется.

🔍 Пример:

a = \[1, 2, 3\] # создаётся список, refcount = 1
b = a # refcount = 2
del a # refcount = 1
del b # refcount = 0 → объект удаляется

❗ Проблема: циклические ссылки

Иногда объекты могут ссылаться друг на друга, образуя цикл. Даже если такие объекты больше не доступны извне, у них может быть ненулевой счётчик ссылок. Это делает невозможным их удаление с помощью одной только подсчётной системы.

🔍 Пример цикла:

class Node:
def \__init_\_(self):
self.link = None
a = Node()
b = Node()
a.link = b
b.link = a
del a
del b
\# refcount не равен 0 — объекты не удаляются автоматически

🔷 2. Сборщик мусора для циклов (GC-модуль)

Чтобы решить проблему циклов, Python использует модуль gc, который запускает алгоритм обнаружения циклических ссылок и удаляет такие объекты.

🔁 Как работает GC в Python

  1. Python делит все объекты на поколения:

    • 0 поколение — новые объекты.

    • 1 поколение — пережили одну проверку.

    • 2 поколение — объекты, давно живущие в памяти.

  2. Проверка мусора начинается с 0-го поколения:

    • Если не удаётся очистить всё — переходит к следующему поколению.

    • Это ускоряет работу: часто мусором оказываются именно новые объекты.

⚙️ Модуль gc

Ты можешь управлять и изучать работу сборщика мусора:

import gc
gc.collect() # Запуск полной сборки мусора
gc.get_threshold() # Порог для запуска по поколениям
gc.get_count() # Кол-во объектов в каждом поколении

📌 Пример:

import gc
print(gc.get_threshold()) # (700, 10, 10) — по умолчанию
print(gc.get_count()) # текущее количество объектов по поколениям

🔷 Признаки "мусора":

Объект считается мусором, если:

  • На него больше нет внешних ссылок;

  • Он не является частью активного стека;

  • Он недостижим из текущего состояния программы.

🧹 Когда вызывается сборщик мусора?

  • Автоматически: когда количество объектов достигает порога.

  • Вручную: с помощью gc.collect()

  • Не всегда немедленно: некоторые объекты удаляются отложенно, особенно при циклических ссылках.

🔐 Управление объектами с __del__

Если у объекта есть метод _del_, он вызывается при удалении. Но в циклических ссылках __del__ может запутать GC, и такие объекты могут не удалиться, если Python не знает, в каком порядке их разрушать.

class A:
def \__del_\_(self):
print("Удаляется!")
a = A()
del a # Выведет: Удаляется!

💡 Как избежать проблем:

  • Избегай циклических ссылок, если можешь.

  • Используй модули weakref или contextlib для контроля объектов.

  • Можно отключить GC, но это не рекомендуется:

gc.disable()
gc.enable()

🧩 Особенности реализации:

  • Python использует счётчики ссылок на уровне интерпретатора CPython.

  • GC основан на алгоритме поколений с циклическим сборщиком.

  • GC работает фоном и автоматически, но его можно контролировать вручную.