Перейти к содержимому
На этой странице

Устройство Python и память

Все темы Python Developer

Подтемы:

Почему sys.getsizeof() недостаточно для оценки памяти контейнера?

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


Почему del не гарантирует немедленное уничтожение объекта?

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


Во что CPython компилирует исходный код?

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


Почему счетчик ссылок не удаляет циклы?

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


Как выбрать профилировщик Python-кода?

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


Как поколения ускоряют cyclic GC?

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


Чем CPython отличается от PyPy и других реализаций?

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


Почему освобожденная память не всегда возвращается ОС?

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


Что такое arena в аллокаторе CPython?

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


Как в питоне работают обращения по ссылкам, что происходит в случаях присваивания, copy, deepcopy?

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

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

В этом случае b становится ссылкой на тот же объект, на который ссылается a. Оба имени (a и b) указывают на один и тот же объект [1, 2, 3].

Присваивание копии объекта выполняется с помощью методов copy() и deepcopy():

1. copy():

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

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

2. deepcopy():

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

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

Поэтому, когда вы работаете с объектами в Python, важно понимать, что присваивание переменной не копирует сам объект, а только создает ссылку на него. Если вам нужна копия объекта, используйте методы copy() или deepcopy().

Собеседования: Python

Смотри записи интервью, узнай, какие вопросы задают и как отвечают кандидаты.

Вопросы и ответы

Не нашли ответ? Напишите мне в чат. Я делаю Шпаргалку и сам отвечаю на сообщения. Расскажите, что не работает или чего вам не хватает. Может, смогу сразу взять это в работу.

Откуда взяты вопросы?

Из реальных собеседований. Основой подборки стал опыт Вадима Новосёлова: он проходил интервью и записывал вопросы. Подробнее о материалах.

Насколько эти вопросы актуальны?

Эти вопросы встречались нам на реальных собеседованиях в 2025 году. Мы регулярно проходим собеседования и пополняем подборку новыми вопросами. Основы профессии и ключевые технологии остаются востребованными годами, а детали конкретных инструментов и версий стоит сверять с текущей документацией.

На какой уровень рассчитана подборка?

Мы проходили собеседования на вакансии уровня Middle+, а иногда и на Senior-позиции. Вопросы из этих интервью вошли в подборку. Направления работы: Python-разработчик, Backend-разработчик на Python. Глубина обсуждения зависит от вакансии: будь готов объяснить основную идею, привести практический пример и разобрать ограничения и альтернативы решения.

Этот вопрос точно будет на моём собеседовании?

Гарантии нет: набор вопросов зависит от компании, задач команды, уровня вакансии и самого интервьюера. Эти вопросы уже встречались на реальных собеседованиях, но на твоём интервью ту же тему могут проверить другой формулировкой, практической задачей или обсуждением твоего опыта. Используй подборку, чтобы разобраться в теме: объясняй идею своими словами, приводи примеры и готовься обсудить ограничения и альтернативы решения. Так будет проще ответить и на знакомый вопрос, и на неожиданные уточнения.