ГлавнаяБлогМассивы в Python: полное руководство
Алгоритмы

Массивы в Python: полное руководство

Узнайте, что такое массивы, как они устроены внутри и когда их использовать. Практические примеры на Python и советы для собеседований. Читайте сейчас!

Al
Редакция Algolitalgolit.ru
12 мин чтения25 августа 2026 г.

Что такое массив и зачем он нужен

Представьте ряд почтовых ящиков: у каждого есть номер (начиная с 0), и в каждом лежит ровно один предмет. Массив — это цифровой аналог такого ряда: коллекция элементов, хранящихся в определённом порядке, где каждый элемент можно найти по его номеру (индексу).

Зачем это нужно? Допустим, нужно хранить результаты тестов 100 студентов. Без массива пришлось бы создать 100 отдельных переменных: score1, score2, ..., score100. А если придёт 101-й студент, код пришлось бы переписывать. Массив решает проблему: используем одну переменную scores и обращаемся к любому результату по индексу.

Ключевые характеристики массива:

  • Упорядоченность: элементы идут в строгой последовательности.
  • Индексируемость: у каждого элемента есть числовой «адрес».
  • Однородность (традиционно): в низкоуровневых языках (C, Java) массив хранит элементы одного типа (например, только целые числа).

Зачем нужны массивы в программировании

Без массивов программирование превратилось бы в кошмар из захардкоженных переменных. Невозможно было бы легко обрабатывать пакеты данных: сортировать списки имён, искать пользователя в базе, рендерить пиксели на экране — всё это потребовало бы тысяч строк повторяющегося кода.

Массивы упрощают:

  • Итерацию: простой цикл для выполнения действия над каждым элементом.
  • Пакетную обработку: передача всего массива в функцию для обработки тысяч элементов разом.
  • Математические операции: массивы — основа линейной алгебры, которая питает 3D-графику и машинное обучение.

Массивы — это «атомы» структур данных. Стеки, очереди, хеш-таблицы и даже управление памятью в ОС построены на массивах. Понимая массивы, вы понимаете фундамент организации данных в компьютере.

Как массивы работают внутри: память и индексация

Чтобы по-настоящему понять массивы, нужно заглянуть в физическую память (RAM).

Непрерывное выделение памяти

При создании массива компьютер находит непрерывный блок свободной памяти и резервирует его. Технический термин — непрерывная память (contiguous memory): адреса памяти идут подряд, без промежутков.

Адреса памяти: 1000   1004   1008   1012   1016
                |------|------|------|------|------|
Значения:       |  10  |  20  |  30  |  40  |  50  |
                |------|------|------|------|------|
Индексы:          0      1      2      3      4

(Предполагается, что каждое число занимает 4 байта)

Индексация с нуля и «смещение»

Почему индексы начинаются с 0, а не с 1? Потому что индекс — это не «номер позиции», а смещение (расстояние) от начала массива. Индекс 0 означает «ноль шагов от начала», индекс 1 — «один шаг».

Вычисление адреса: доступ O(1)

Когда вы обращаетесь к array[3], компьютер не перебирает элементы один за другим, а вычисляет адрес по формуле:

Адрес = Базовый адрес + (Индекс × Размер элемента)

Для примера выше: базовый адрес 1000, размер элемента 4 байта, индекс 3. Адрес = 1000 + (3 × 4) = 1012. Компьютер мгновенно переходит к ячейке 1012 и читает значение 40. Так как используется одно математическое уравнение, доступ к элементу по индексу всегда мгновенен — в Computer Science это называется временная сложность O(1) (константное время).

Когда использовать массивы, а когда нет

Когда массивы — хороший выбор

  • Произвольный доступ: нужно часто обращаться к элементам по позиции (например, «получить 500-го пользователя»).
  • Последовательный доступ: нужно перебрать все элементы от начала до конца (например, отправить письма всем пользователям).
  • Экономия памяти: вы точно знаете, сколько элементов нужно, или их количество стабильно.

Когда массивы — плохой выбор

  • Частые вставки/удаления в середине: если у вас 1000 элементов и нужно удалить 5-й, придётся сдвинуть оставшиеся 995 элементов влево — это медленно.
  • Неизвестный и огромный размер: если непонятно, сколько данных будет, массив фиксированного размера либо тратит память, либо приводит к ошибке.

Статические и динамические массивы

  • Статические (фиксированные): размер задаётся при создании и не меняется. Очень быстрые и экономные (как в C).
  • Динамические (как list в Python или ArrayList в Java): внутри — обычный статический массив, но при заполнении создаётся новый, большего размера, и все элементы копируются.

Сложность операций: время и память

Вот профиль производительности стандартного динамического массива:

ОперацияТипичная сложностьПочему
Доступ по индексуO(1)Математическая формула мгновенно вычисляет адрес.
Поиск по значениюO(n)В худшем случае нужно проверить каждый элемент.
Вставка в началоO(n)Нужно сдвинуть все существующие элементы вправо.
Вставка в серединуO(n)В среднем сдвиг половины элементов.
Вставка в конецO(1)*Просто кладём в следующую свободную ячейку.
Удаление из началаO(n)Сдвиг всех оставшихся элементов влево.
Удаление из серединыO(n)В среднем сдвиг половины элементов.
Удаление из концаO(1)Просто удаляем и уменьшаем счётчик.

*Примечание: в динамическом массиве иногда происходит увеличение размера (копирование всех элементов в новый блок) — это O(n). Но так как это случается редко, амортизированная сложность остаётся O(1).

Массивы против других структур данных

Массивы vs связные списки

  • Массив: элементы «склеены» в памяти. Быстрое чтение (O(1)), медленные вставка/удаление в середине (O(n)).
  • Связный список: элементы разбросаны, но каждый хранит указатель на следующий. Медленное чтение (нужно идти по цепочке, O(n)), быстрые вставка/удаление (просто меняем указатели, O(1)).

Массивы vs стеки и очереди

Стек (LIFO) и очередь (FIFO) — это концепции или правила поведения данных. Массив — физическая структура, на которой они строятся. Стек — это массив, где добавление и удаление происходит только с конца.

Массивы vs хеш-таблицы (словари)

  • Массив: поиск по целочисленному индексу.
  • Хеш-таблица: поиск по уникальному ключу (например, имя пользователя). Внутри хеш-таблица использует массив: ключ прогоняется через хеш-функцию, которая преобразует его в индекс.

Практические примеры в реальном ПО

  • Хранение списка пользователей: идеально для массива, так как обычно просто перебираем их или обращаемся по индексу.
  • Обработка изображений: изображение — это огромный одномерный или двумерный массив пикселей. Каждый пиксель — массив из 3-4 чисел (Red, Green, Blue, Alpha). Массивы нужны для быстрой обработки миллионов пикселей благодаря O(1) доступу и непрерывной памяти (что полезно для кэша CPU).
  • Временные ряды: цены акций за год. Добавляем дневную цену в конец массива, редко удаляем старые данные, часто смотрим последние 30 дней (последовательный доступ).
  • Матрицы в машинном обучении: нейросети выполняют миллиарды умножений. Только массивы (особенно оптимизированные многомерные) позволяют эффективно хранить и вычислять данные.

Пример на Python: списки как динамические массивы

# Создание списка (в Python это динамический массив)
scores = [85, 92, 78, 90]

# Доступ по индексу (O(1))
print(scores[0])  # Вывод: 85

# Итерация (последовательный доступ)
for score in scores:
    print(score)

# Добавление в конец (амортизированное O(1))
scores.append(95)

Важное отличие Python: список в Python — это не традиционный массив C с сырыми значениями. Внутри это массив указателей на объекты. Сам массив непрерывен, но объекты (числа, строки и т.д.) разбросаны по памяти.

Динамическое расширение: когда список заполняется, он не увеличивается на 1 элемент, а выделяет с запасом (обычно +12.5%), чтобы будущие append() оставались быстрыми.

Альтернативы для низкоуровневой работы:

  • array.array: встроенный модуль, хранит сырые C-значения (только числа) непрерывно. Гораздо экономнее по памяти, чем list.
  • NumPy массивы (numpy.ndarray): стандарт для науки о данных. Настоящие многомерные непрерывные C-массивы. Позволяют «векторизацию» — математические операции над всем массивом на скорости C без циклов Python.

Реальный пример: поиск самой длинной серии достижений

Задача: вы создаёте фитнес-приложение. У вас есть массив количества шагов за последние 30 дней:

steps = [4000, 8000, 10500, 12000, 5000, 11000, 13000, 14000]

Нужно найти самую длинную серию подряд идущих дней, когда пользователь достиг цели в 10000 шагов.

Почему массив? Нам нужно последовательно просматривать данные день за днём, быстро обращаться к элементам (O(1)) и не требуется вставка/удаление.

Решение на Python:

steps = [4000, 8000, 10500, 12000, 5000, 11000, 13000, 14000]
goal = 10000
max_streak = 0
current_streak = 0

# Последовательный доступ: O(n)
for daily_steps in steps:
    if daily_steps >= goal:
        current_streak += 1  # Увеличиваем текущую серию
        if current_streak > max_streak:
            max_streak = current_streak  # Обновляем рекорд
    else:
        current_streak = 0  # Сброс при неудачном дне

print(f"Самая длинная серия: {max_streak} дней")  # Вывод: 3

Мы проходим по массиву один раз (O(n)), храним текущую серию и максимальную. Это эффективно и использует O(1) дополнительной памяти.

Главные выводы

Золотое правило: доступ к элементу — O(1), вставка/удаление — O(n). Используйте массивы, когда часто читаете данные и редко меняете структуру.

Непрерывная память: массивы «склеены» в RAM, что ускоряет обработку (кэш-дружественность), но требует достаточно большого непрерывного блока для создания крупного массива.

Индекс 0 — это смещение: индекс 0 означает «нулевое расстояние от начала».

Частые ошибки новичков:

  • Ошибка на единицу: попытка обратиться к array[length] вместо array[length - 1]. Если в массиве 5 элементов, последний индекс — 4.
  • Изменение массива во время итерации: удаление элементов в цикле сдвигает индексы, что приводит к пропуску элементов или ошибкам.
  • Забывать, что списки Python — не C-массивы: они хранят ссылки на объекты, что влияет на память и производительность в математических вычислениях.

Что делать прямо сейчас

Откройте редактор и напишите функцию, которая принимает массив чисел и возвращает новый массив, где каждый элемент — это произведение всех остальных элементов, кроме текущего (например, для [1,2,3,4] результат [24,12,8,6]). Попробуйте решить за O(n) без деления. Это отличная тренировка понимания массивов!

#массивы#структуры данных#Python#сложность алгоритмов#собеседование
Al
Редакция Algolit

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

Хочешь закрепить знания на практике?

Решай задачи на Algolit — интерактивная платформа для обучения

Начать бесплатно →