Как работает сборщик мусора в 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
-
Python делит все объекты на поколения:
-
0 поколение — новые объекты.
-
1 поколение — пережили одну проверку.
-
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 работает фоном и автоматически, но его можно контролировать вручную.