Python list и array: ключевые отличия

Раздел: Основы Python -> Сравнение типов

Сравнение списков и массивов в Python

Для выбора между списком и массивом важно понимать их ключевые различия. Основное эффективное решение: применять list в качестве универсального контейнера, допускающего разнородные данные. Если требуется экономия памяти при работе с однотипными числовыми значениями, лучше использовать array из модуля array. Ниже приведён пример, иллюстрирующий разницу в потреблении памяти.

import sys, array

lst = [1, 2, 3, 4, 5]
arr = array.array('i', [1, 2, 3, 4, 5])

print('Размер списка:', sys.getsizeof(lst))
print('Размер массива:', sys.getsizeof(arr))

Python list массив (список и массив в python)

Размер списка: 104
Размер массива: 68

Массив занимает меньше места за счёт хранения однородных данных плотной упаковкой. Однако список остаётся более гибким: в него можно помещать элементы любых типов.

Как создать список с элементами разных типов?

Список объявляется с помощью квадратных скобок. Допустимы любые объекты, включая вложенные структуры.

mixed = [42, "текст", 3.14, (1, 2), ["a", "b"]]
print(mixed)
[42, 'текст', 3.14, (1, 2), ['a', 'b']]

Типичная ошибка - попытка вставить нечисловой элемент в массив array, если он уже задан числовым типом. Список таких ограничений не имеет. Для списка потенциальная проблема - непреднамеренное смешение типов, что может замедлить работу при больших объёмах.

Как создать массив целых чисел из модуля array?

Импортируйте модуль array и укажите символ типа (например, 'i' для знакового целого).

import array
arr = array.array('i', [10, 20, 30])
print(arr)
array('i', [10, 20, 30])

Распространённая ошибка - использование неподдерживаемого символа типа или попытка добавить значение несовместимого типа (например, строку). При этом возникает TypeError.

arr.append("строка")
TypeError: 'str' object cannot be interpreted as an integer

Как преобразовать список в массив?

Для преобразования достаточно передать список в конструктор array с нужным типом.

lst = [1, 2, 3]
arr = array.array('i', lst)
print(arr)
array('i', [1, 2, 3])

Если список содержит элементы, не соответствующие указанному типу, будет выброшено исключение. Рекомендуется предварительно проверять типы или использовать списковое включение для приведения.

Как выполнить поэлементные арифметические операции над массивом?

Модуль array не предоставляет встроенных поэлементных операций. Можно воспользоваться списковым включением или циклом.

arr = array.array('i', [1, 2, 3])
doubled = array.array('i', [x * 2 for x in arr])
print(doubled)
array('i', [2, 4, 6])

Непосредственное умножение массива на число (например, arr * 2) повторяет содержимое, а не умножает элементы. Это частая путаница.

print(arr * 2)
array('i', [1, 2, 3, 1, 2, 3])

Расширенные примеры работы со списками и массивами

Сравнение производительности при вставке и удалении элементов

Список оптимизирован для частых изменений размера, массив - статичнее, но быстрее при последовательном чтении.

Пример
import time
lst = list(range(100000))
arr = array.array('i', range(100000))

# Вставка в середину
start = time.time()
lst.insert(50000, -1)
print('list insert:', time.time() - start)

start = time.time()
arr.insert(50000, -1)
print('array insert:', time.time() - start)
list insert: 0.0009
array insert: 0.0021

Как видно, вставка в массив может быть медленнее из-за необходимости проверки типа.

Бинарный ввод-вывод с массивами

Массивы поддерживают методы tofile и fromfile, что удобно для работы с бинарными файлами.

Пример
import array
arr = array.array('d', [1.5, 2.7, 3.14])
with open('data.bin', 'wb') as f:
    arr.tofile(f)

with open('data.bin', 'rb') as f:
    restored = array.array('d')
    restored.fromfile(f, 3)
print(restored)
array('d', [1.5, 2.7, 3.14])

Для списков подобная функциональность отсутствует, потребуется модуль struct или pickle.

Использование массивов разных числовых типов

Модуль array поддерживает несколько кодов типов: 'b' (signed char), 'B' (unsigned char), 'f' (float), 'd' (double) и другие. Следует учитывать возможное переполнение.

Пример
import array
b_arr = array.array('b', [127, -128])
print('b_arr:', b_arr)
# Попытка записать значение вне диапазона
try:
    b_arr.append(128)
except OverflowError as e:
    print('Ошибка:', e)
b_arr: array('b', [127, -128])
Ошибка: signed char is greater than maximum

Поэлементная обработка с помощью map и filter

Списки и массивы поддерживают функции map и filter, результат которых требуется преобразовать обратно в нужный тип.

Пример
arr = array.array('i', [1, 2, 3, 4])
mapped = array.array('i', map(lambda x: x ** 2, arr))
print(mapped)

filtered = array.array('i', filter(lambda x: x > 2, arr))
print(filtered)
array('i', [1, 4, 9, 16])
array('i', [3, 4])

Аналогично для списков: результат map даёт итератор, его нужно обернуть в list.

Список и массив в Python - comments

En
Python list массив (python)