0Pricing
Python Academy · Урок

Подсчёт ссылок в 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))   # 3

sys.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 — локальная установка не требуется.

Все уроки этого курса

  1. Подсчёт ссылок в CPython
  2. Сборщик мусора и циклические ссылки
  3. Профилирование с cProfile и line_profiler
  4. Профилирование памяти с tracemalloc
← Назад к Python Academy