← Назад к вопросам

Как Python хранит данные в памяти?

2.8 Senior🔥 131 комментариев
#Тестирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как Python хранит данные в памяти

Python использует механизм управления памятью на основе объектов и ссылок. Каждый объект содержит метаданные и значение.

Структура объекта в памяти

Каждый объект Python состоит из трёх компонентов:

import sys

# 1. Тип объекта
obj = 42
print(type(obj))  # <class "int">

# 2. Счётчик ссылок (reference count)
print(sys.getrefcount(obj))  # количество ссылок на объект

# 3. Значение
print(obj)  # 42

PyObject — базовая структура для всех объектов:

  • ob_refcnt — счётчик ссылок (для garbage collection)
  • ob_type — указатель на объект типа (metaclass)
  • Дополнительные данные (зависит от типа)

Управление памятью: Reference Counting

Python использует подсчёт ссылок (reference counting) — основной механизм управления памятью.

import sys

a = []
print(sys.getrefcount(a))  # 2 (сама переменная + аргумент функции)

b = a  # ещё одна ссылка
print(sys.getrefcount(a))  # 3

del b  # удалили ссылку
print(sys.getrefcount(a))  # 2 снова

Когда счётчик ссылок падает до 0, объект немедленно удаляется из памяти.

Сборка мусора (Garbage Collection)

Однако reference counting не решает проблему циклических ссылок:

# Циклическая ссылка
class Node:
    def __init__(self, value):
        self.value = value
        self.next = None

a = Node(1)
b = Node(2)
a.next = b
b.next = a  # циклическая ссылка!

del a
del b
# Объекты остаются в памяти, так как друг на друга ссылаются!

Для этого Python имеет сборщик мусора (garbage collector), который периодически ищет и удаляет циклические ссылки.

import gc

# Принудительно запустить сборку мусора
gc.collect()

# Отключить/включить
gc.disable()
gc.enable()

Интернирование строк и небольших целых чисел

Python оптимизирует память через интернирование — переиспользование одного объекта для нескольких переменных:

# Небольшие целые числа (-5 до 256) интернируются
a = 5
b = 5
print(a is b)  # True! Один и тот же объект в памяти
print(id(a) == id(b))  # True

# Для больших чисел — разные объекты
x = 257
y = 257
print(x is y)  # False (в REPL может быть True, но в скрипте False)

# Строки тоже интернируются
s1 = "hello"
s2 = "hello"
print(s1 is s2)  # True

Стек (Stack) и куча (Heap)

Python хранит:

  • На стеке: локальные переменные (ссылки на объекты)
  • На куче: сами объекты
def foo():
    a = [1, 2, 3]  # ссылка `a` на стеке, список на куче
    b = a          # ещё одна ссылка на тот же список
    return b

result = foo()  # переменная result указывает на список на куче
# Когда функция завершилась, `a` и `b` удалены со стека,
# но объект список остаётся, так как на него есть ссылка result

Практический пример

import sys

# 1. Создание объекта
my_list = [1, 2, 3]
print(f"ID объекта: {id(my_list)}")
print(f"Размер в памяти: {sys.getsizeof(my_list)} байт")
print(f"Счётчик ссылок: {sys.getrefcount(my_list)}")

# 2. Ещё одна ссылка
my_list_copy = my_list
print(f"После присваивания: {sys.getrefcount(my_list)}")  # +1

# 3. Проверка идентичности
print(f"my_list is my_list_copy: {my_list is my_list_copy}")  # True

# 4. Удаление ссылки
del my_list_copy
print(f"После del: {sys.getrefcount(my_list)}")  # -1

Ключевые выводы

  • Все данные хранятся как объекты на куче (heap)
  • Переменные — это ссылки на объекты
  • Reference counting автоматически удаляет объекты при нулевом числе ссылок
  • Garbage collector избавляет от циклических ссылок
  • Интернирование экономит память для маленьких объектов
  • Понимание этого важно для оптимизации памяти и избежания утечек памяти
Как Python хранит данные в памяти? | PrepBro