---
title: Устройство Python и память
questionDates:
  q-transfer-0253: '2026-10-01'
  q-transfer-0254: '2026-10-01'
  q-transfer-0255: '2026-10-01'
  q-transfer-0256: '2026-10-01'
  q-transfer-0257: '2026-10-01'
  q-transfer-0280: '2026-10-01'
  q-transfer-0281: '2026-10-01'
  q-transfer-0282: '2026-10-01'
  q-transfer-0285: '2026-10-01'
seo:
  description: >-
    Тема «Устройство Python и память» для собеседования Python Developer. Почему
    sys.getsizeof() недостаточно для оценки памяти контейнера? Почему del не
    гарантирует немедленное уничтожение объекта?
  title: Устройство Python и память — Python Developer
---

[Все темы Python Developer](/prep/python-developer)

Подтемы:

- [Устройство Python и память](#q-transfer-0253)
- [Ссылки](#q-14bee738d69b8131b2b9f8091ed28343)

## Почему sys.getsizeof() недостаточно для оценки памяти контейнера? [#q-transfer-0253]

`sys.getsizeof(container)` показывает собственный размер объекта, включая массив ссылок, но не проходит по объектам, на которые он ссылается. Рекурсивный подсчет должен учитывать вложенность, совместно используемые ссылки и циклы, иначе данные будут недосчитаны или посчитаны дважды. Для реальной утечки полезнее `tracemalloc` и профиль процесса; RSS включает также allocator, native-библиотеки и фрагментацию. Это детали реализации CPython, поэтому семантику программы нельзя строить на точном моменте освобождения или внутреннем размере блока.

:::note[Ссылки для изучения]

1. [Ограничения sys.getsizeof: размер объекта без содержимого по ссылкам — документация Python](https://pythondoc.ru/docs/python/3.10/library/sys/#sys.getsizeof)
   :::

---

## Почему del не гарантирует немедленное уничтожение объекта? [#q-transfer-0254]

`del name` удаляет привязку имени, а не приказ уничтожить объект. Пока существуют другие ссылки, объект жив. CPython обычно освобождает объект сразу при нулевом счетчике ссылок, но циклы может убрать позже cyclic GC; другие реализации Python не обязаны следовать этому времени. Финализацию и закрытие файла нельзя строить на моменте сборки мусора, для ресурсов используют `with` или явный `close`. Это детали реализации CPython, поэтому семантику программы нельзя строить на точном моменте освобождения или внутреннем размере блока.

:::note[Ссылки для изучения]

1. [Сборка мусора и время жизни объектов: почему ресурсы закрывают явно — документация Python](https://docs.python.org/ru/3/reference/datamodel.html#objects-values-and-types)
2. [del и время уничтожения. Python Clinic, с 1:07](https://www.youtube.com/watch?v=a_ZBO_bqvB0&t=67s)

:::

---

## Во что CPython компилирует исходный код? [#q-transfer-0255]

Обычный CPython компилирует модуль в bytecode code objects, которые исполняет виртуальная машина; кэш может храниться в `__pycache__`. Это не машинный код и не сокрытие исходной логики. Другие реализации выбирают другую стратегию: PyPy применяет JIT, а Cython переводит расширенный Python в C для последующей компиляции. Упаковщик executable обычно собирает runtime и файлы, а не превращает программу в нативный код целиком. Это детали реализации CPython, поэтому семантику программы нельзя строить на точном моменте освобождения или внутреннем размере блока.

:::note[Ссылки для изучения]

1. [Байт-код CPython, виртуальная машина и кэш .pyc — документация Python](https://docs.python.org/ru/3/glossary.html#term-bytecode)
   :::

---

## Почему счетчик ссылок не удаляет циклы? [#q-transfer-0256]

В цикле объекты держат ссылки друг на друга, поэтому их счетчики не достигают нуля даже после потери всех внешних ссылок. Cyclic GC в CPython периодически ищет такие недостижимые группы среди отслеживаемых контейнеров и освобождает их. Счетчик ссылок остается быстрым механизмом для большинства объектов. Циклы с ресурсами все равно нельзя оставлять на GC: соединения и файлы закрывают детерминированно. Это детали реализации CPython, поэтому семантику программы нельзя строить на точном моменте освобождения или внутреннем размере блока.

:::note[Ссылки для изучения]

1. [Циклическая ссылка списка: почему refcount не достигает нуля — разбор CPython](https://habr.com/ru/articles/463269/)
2. [Циклические ссылки. Python Clinic, с 8:41](https://www.youtube.com/watch?v=a_ZBO_bqvB0&t=521s)

:::

---

## Как выбрать профилировщик Python-кода? [#q-transfer-0257]

Сначала фиксируют воспроизводимый сценарий и измеряют wall time, throughput или память. `cProfile` показывает суммарное и собственное время функций, `line_profiler` ищет дорогие строки, `tracemalloc` сравнивает выделения Python-памяти. Для I/O нужны трассировки и ожидания, а не только CPU-профиль. После изменения повторяют тот же benchmark с прогревом и несколькими запусками, иначе оптимизируют шум или не тот слой. Это детали реализации CPython, поэтому семантику программы нельзя строить на точном моменте освобождения или внутреннем размере блока.

:::note[Ссылки для изучения]

1. [Выбор уровня профилирования: функции в cProfile и строки в line_profiler — Мартин Хайнц](https://habr.com/ru/companies/wunderfund/articles/656571/)
   :::

---

## Как поколения ускоряют cyclic GC? [#q-transfer-0280]

Cyclic GC CPython группирует отслеживаемые объекты по поколениям, исходя из наблюдения, что многие умирают молодыми. Молодое поколение проверяется чаще; выжившие продвигаются и обходятся реже, поэтому уменьшается средняя стоимость поиска циклов. Полная сборка дороже и не обязана вернуть память ОС. Детали поколений и пороги менялись между версиями CPython, поэтому на них нельзя строить семантику программы. Это детали реализации CPython, поэтому семантику программы нельзя строить на точном моменте освобождения или внутреннем размере блока.

:::note[Ссылки для изучения]

1. [Поколения cyclic GC: продвижение выживших объектов и частота сборок — документация Python 3.10](https://pythondoc.ru/docs/python/3.10/library/gc/#gc.set_threshold)
   :::

---

## Чем CPython отличается от PyPy и других реализаций? [#q-transfer-0281]

CPython является основной реализацией с большим набором C-расширений. PyPy применяет JIT и может ускорять долгоживущий чистый Python, но совместимость и профиль памяти расширений отличаются. Jython работает на JVM, IronPython на .NET, MicroPython рассчитан на микроконтроллеры и имеет урезанную библиотеку. Выбор проверяют по нужной версии языка, native-зависимостям, latency прогрева и реальному benchmark. Это детали реализации CPython, поэтому семантику программы нельзя строить на точном моменте освобождения или внутреннем размере блока.

:::note[Ссылки для изучения]

1. [CPython, PyPy, Jython и IronPython: обзор альтернативных реализаций — документация Python](https://docs.python.org/ru/3/reference/introduction.html#alternate-implementations)
   :::

---

## Почему освобожденная память не всегда возвращается ОС? [#q-transfer-0282]

Удаление объекта освобождает его память для allocator CPython, но не обязательно уменьшает RSS процесса. Малые объекты размещаются в blocks, pools и arenas; пока arena содержит живые blocks, ее нельзя целиком вернуть ОС. Добавляются фрагментация, кэши и память native-библиотек. Поэтому различают логическую утечку растущих живых объектов и удержание уже свободной памяти allocator, используя `tracemalloc` и метрики процесса вместе. Это детали реализации CPython, поэтому семантику программы нельзя строить на точном моменте освобождения или внутреннем размере блока.

:::note[Ссылки для изучения]

1. [Почему удаление блоков не освобождает занятую арену: память pymalloc — Домклик](https://habr.com/ru/amp/publications/530804/)
   :::

---

## Что такое arena в аллокаторе CPython? [#q-transfer-0285]

В `pymalloc` CPython arena является крупным участком памяти, разделенным на pools, а pools на blocks фиксированных size classes для малых объектов. Объект может быть освобожден, но arena остается у процесса, пока в ней есть занятые pools. Это часть allocator, а не поколение и не алгоритм cyclic GC. Точные размеры и правила являются деталями конкретной версии CPython. Это детали реализации CPython, поэтому семантику программы нельзя строить на точном моменте освобождения или внутреннем размере блока.

:::note[Ссылки для изучения]

1. [Арены, пулы и блоки в аллокаторе pymalloc — разбор Домклика](https://habr.com/ru/amp/publications/530804/)
   :::

---

## <strong>Как в питоне работают обращения по ссылкам, что происходит в случаях присваивания, copy, deepcopy?</strong> [#q-14bee738d69b8131b2b9f8091ed28343]

В Python переменные представляют собой ссылки на объекты. Когда вы присваиваете значение переменной, вы фактически создаете ссылку на объект в памяти, а не копируете сам объект. Рассмотрим, как это работает на примере&#58;

```python
a = [1, 2, 3]
b = a
```

В этом случае <code>b</code> становится ссылкой на тот же объект, на который ссылается <code>a</code>. Оба имени (<code>a</code> и <code>b</code>) указывают на один и тот же объект <code>&#91;1&#44; 2&#44; 3&#93;</code>.

Присваивание копии объекта выполняется с помощью методов <code>copy&#40;&#41;</code> и <code>deepcopy&#40;&#41;</code>&#58;

<strong>1&#46; copy()</strong>&#58;

```python
a = [1, 2, 3]
b = a.copy()
```

Этот метод создает поверхностную копию объекта. Это означает, что он создает новый объект, который содержит ссылки на те же объекты, что и исходный объект (если он является контейнером, таким как список). Поэтому изменения вложенных объектов будут отражаться как в копии, так и в исходном объекте.

<strong>2&#46; deepcopy()</strong>&#58;

```python
import copy
a = [[1, 2], [3, 4]]
b = copy.deepcopy(a)
```

Этот метод создает полную копию объекта. Он рекурсивно копирует все вложенные объекты, создавая новые объекты для каждого из них. Таким образом, изменения в копии не будут влиять на исходный объект, и наоборот.

Поэтому, когда вы работаете с объектами в Python, важно понимать, что присваивание переменной не копирует сам объект, а только создает ссылку на него. Если вам нужна копия объекта, используйте методы <code>copy&#40;&#41;</code> или <code>deepcopy&#40;&#41;</code>.

:::note[Ссылки для изучения]

1. [Присваивание, поверхностная и глубокая копия объектов — документация Python](https://pythondoc.ru/docs/python/3.10/library/copy/)
   :::
