В Python используется комбинация двух подходов:
Каждый объект в Python содержит счетчик ссылок, который увеличивается при создании новой ссылки и уменьшается при удалении ссылки.
import sys
a = [] # Создаем объект, счетчик = 1
b = a # Счетчик увеличивается до 2
print(sys.getrefcount(a)) # Выведет 3 (временная ссылка при вызове функции)
del b # Счетчик уменьшается до 1
# Когда счетчик достигает 0, память немедленно освобождается
Преимущества:
Недостатки:
Решает проблему циклических ссылок, используя алгоритм "поколений" (generational):
class Node:
def __init__(self):
self.parent = None
self.children = []
# Создаем циклическую ссылку
node1 = Node()
node2 = Node()
node1.children.append(node2)
node2.parent = node1
# Даже если удалить внешние ссылки, счетчик не обнулится
del node1
del node2
# Здесь вступает в работу Generational GC
import gc
print(gc.get_threshold()) # Покажет пороги для каждого поколения (700, 10, 10)
import gc
# Отключение автоматического GC (не рекомендуется)
gc.disable()
# Принудительный запуск сборки мусора
gc.collect() # Для всех поколений
gc.collect(0) # Только Generation 0
# Настройка параметров
gc.set_threshold(1000, 15, 15) # (threshold0, threshold1, threshold2)
Метод __del__
может помешать сборке мусора:
class A:
def __del__(self):
print("Удаляется A")
class B:
def __del__(self):
print("Удаляется B")
a = A()
b = B()
a.b = b
b.a = a # Циклическая ссылка
del a
del b
# Объекты не будут удалены из-за наличия __del__ и циклической ссылки
Альтернатива для избежания циклических ссылок:
import weakref
class Node:
def __init__(self):
self.parent = None
self._children = weakref.WeakSet()
def add_child(self, child):
self._children.add(child)
child.parent = self
import gc
# Получение списка "подозрительных" объектов
gc.set_debug(gc.DEBUG_LEAK) # Включение режима отладки
gc.collect()
# Анализ объектов в памяти
for obj in gc.get_objects():
if isinstance(obj, SomeClass):
print(f"Обнаружен объект: {obj}")
__del__
может помешать сборке мусораgc
Python автоматически управляет памятью, но понимание работы GC помогает писать более эффективный код и избегать утечек памяти.