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

Какая проблема Python при работе со списками с точки зрения работы с памятью?

2.2 Middle🔥 111 комментариев
#Python Core#Архитектура и паттерны

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

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

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

Проблемы Python списков с памятью

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

Главная проблема: Переиспользование памяти

Просто говоря, Python список занимает значительно больше памяти, чем сами данные в нём. Причина — динамическое расширение массива.

import sys

# Пустой список занимает уже 56 байт
print(sys.getsizeof([]))  # 56

# Список с 10 числами занимает 152 байта
my_list = list(range(10))
print(sys.getsizeof(my_list))  # 152

# Но каждое целое число тоже занимает память
for i in my_list:
    print(sys.getsizeof(i))
    # Каждое число — минимум 28 байт (на 64-бит системе)

Стратегия выделения памяти

Когда список растёт, Python выделяет памяти больше, чем нужно для будущих добавлений:

import sys

mem_usage = []
for i in range(50):
    my_list = []
    for j in range(i):
        my_list.append(j)
    mem_usage.append((i, sys.getsizeof(my_list)))

for count, size in mem_usage[:10]:
    print(f"Элементов: {count:3}, памяти: {size:4} байт")

Проблема: Много ссылок вместо данных

Список хранит не сами данные, а ссылки (указатели) на объекты:

my_list = [1, 2, 3, 4, 5]

# Реальная структура в памяти:
# [указатель на 1] [указатель на 2] [указатель на 3] ...

# Каждое целое число — отдельный объект с overhead'ом
# Объект int занимает ~28 байт, хотя само число = 8 байт

Решение 1: Используйте array модуль

import array
import sys

# Для больших наборов однородных данных
my_array = array.array('i', range(1000000))
print(sys.getsizeof(my_array))

Решение 2: Используйте numpy для числовых данных

import numpy as np

python_list = list(range(1000000))
numpy_array = np.arange(1000000)

print(f"numpy: {numpy_array.nbytes / 1024 / 1024:.2f} MB")

Решение 3: Генераторы вместо списков

# Список — всё в памяти
my_list = [x * 2 for x in range(1000000)]

# Генератор — вычисляет по мере необходимости
my_gen = (x * 2 for x in range(1000000))

Выводы

  • Python списки занимают в 2-3 раза больше памяти
  • Используйте array для однородных числовых данных
  • Используйте numpy для научных вычислений
  • Используйте генераторы для больших последовательностей