Подсчёт ссылок в CPython
Разберитесь, как CPython отслеживает время жизни объектов с помощью счётчиков ссылок.
«Подсчёт ссылок в CPython» — бесплатный урок Python Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Python Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Python Academy содержит 4 уроков всего.
Что такое подсчёт ссылок
CPython отслеживает счётчик ссылок каждого объекта. Когда счётчик уменьшается до 0, объект немедленно освобождается. Это основной механизм управления памятью в Python.
import sys
x = [1, 2, 3]
print(sys.getrefcount(x)) # 2 (x + getrefcount arg)
y = x
print(sys.getrefcount(x)) # 3sys.getrefcount()
sys.getrefcount(obj) возвращает текущий счётчик ссылок. Обратите внимание: вызов добавляет 1 к счётчику (ссылка на аргумент функции).
import sys
a = "hello"
print(sys.getrefcount(a)) # baseline (may be high for interned strings)
b = a
print(sys.getrefcount(a)) # one more
del b
print(sys.getrefcount(a)) # back to baselineУвеличение и уменьшение
Каждое присваивание увеличивает счётчик, а каждое удаление или повторное присваивание уменьшает его. Когда счётчик достигает 0, CPython вызывает функцию освобождения объекта.
x = [] # refcount = 1
y = x # refcount = 2
z = [x] # refcount = 3 (list holds a reference)
del y # refcount = 2
z.clear() # refcount = 1
del x # refcount = 0 → deallocatedИнтернирование объектов
CPython интернирует небольшие целые числа (от -5 до 256) и множество строковых литералов, повторно используя один и тот же объект. Сравнения с помощью is позволяют это увидеть.
a = 256
b = 256
print(a is b) # True (interned)
c = 257
d = 257
print(c is d) # may be False (not interned)Слабые ссылки
Слабые ссылки не увеличивают счётчик ссылок. Они полезны, чтобы не препятствовать сборке мусора для объектов, которые Вы хотите наблюдать, но которыми не владеете.
import weakref
class BigObject:
pass
obj = BigObject()
ref = weakref.ref(obj)
print(ref()) # <BigObject instance>
del obj
print(ref()) # None (object was collected)Циклы ссылок
Если A ссылается на B, а B — на A, ни один объект не достигает 0, даже когда оба недоступны. Циклический сборщик мусора CPython обнаруживает и собирает такие объекты.
a = []
b = [a]
a.append(b) # cycle: a → b → a
del a, b
# Both are unreachable but refcount > 0
# The cyclic GC collects themМодуль gc
Модуль gc предоставляет циклический сборщик мусора. Он запускается автоматически, но его можно запустить вручную или отключить.
import gc
gc.collect() # force a collection cycle
print(gc.get_count()) # (gen0, gen1, gen2) allocation counts
print(gc.get_threshold()) # when each generation is collectedПулы памяти (pymalloc)
CPython выделяет небольшие объекты (< 512 байт) из собственного пула памяти (pymalloc), который работает быстрее, чем вызов malloc для каждого небольшого объекта.
# You do not call pymalloc directly — CPython uses it internally
# for all Python-level object allocations
# The pool pre-allocates large memory arenas
# and carves them into pools of fixed-size blocksФинализаторы __del__
__del__ вызывается, когда счётчик ссылок объекта достигает 0 (или позже, если объект участвует в цикле). Не полагайтесь на него для критически важного освобождения ресурсов — вместо этого используйте менеджеры контекста.
class Resource:
def __del__(self):
print(f"Freeing {self}")
# Better: use context manager
class SafeResource:
def __enter__(self): return self
def __exit__(self, *a): self.cleanup()Компактные объекты с __slots__
Объекты с __slots__ используют меньше памяти и требуют меньше выделений, снижая нагрузку на сборщик мусора.
import sys
class Reg:
def __init__(self, x, y): self.x, self.y = x, y
class Slotted:
__slots__ = ("x","y")
def __init__(self, x, y): self.x, self.y = x, y
print(sys.getsizeof(Reg(1,2))) # ~48 + dict overhead
print(sys.getsizeof(Slotted(1,2))) # ~48 (no dict)Отключение циклического сборщика мусора
Для программ, не создающих циклы ссылок, отключение циклического сборщика мусора может повысить пропускную способность.
import gc
gc.disable() # no cyclic GC — objects are only freed by refcounting
# Use only if you KNOW no cycles are created
# (pure functional/immutable data)
gc.enable() # re-enableБыстрая проверка
Когда CPython немедленно освобождает объект?
Итоги
CPython отслеживает объекты с помощью счётчиков ссылок. Счётчик достигает 0 → объект немедленно освобождается. Циклы ссылок обрабатывает циклический сборщик мусора (модуль gc). Не используйте __del__ для критически важного освобождения ресурсов; применяйте менеджеры контекста. Используйте __slots__, чтобы уменьшить объём памяти на объект.
Часто задаваемые вопросы
Урок «Подсчёт ссылок в CPython» бесплатный?
Да — полный текст урока «Подсчёт ссылок в CPython» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Python Academy, подпишись на CoddyKit PRO. Курс Python Academy содержит 4 уроков всего.
Чему я научусь в уроке «Подсчёт ссылок в CPython»?
Разберитесь, как CPython отслеживает время жизни объектов с помощью счётчиков ссылок. Ты практикуешь Python Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Python Academy?
Предыдущий опыт не требуется. Python Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Подсчёт ссылок в CPython»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Python Academy?
Да. Каждый урок Python Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Подсчёт ссылок в CPython
- Сборщик мусора и циклические ссылки
- Профилирование с cProfile и line_profiler
- Профилирование памяти с tracemalloc