Как создать список с определенным размером на Python

  1. Предварительное размещение хранилища для списков
  2. Предварительное выделение хранилища для других последовательных структур данных

Предварительное выделение хранилища для списков или массивов - типичный шаблон среди программистов. когда они заранее знают количество элементов.

В отличие от C++ и Java, в Python, вы должны инициализировать все ваше предварительно распределенное хранилище некоторыми значениями. Обычно разработчики используют для этого ложные значения, такие как None, "", False и 0.

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

Для сравнения характеристик различных подходов мы будем использовать стандарт Python модуль timeit. Он предоставляет удобный способ измерения времени выполнения небольших фрагментов кода Python.

Предварительное размещение хранилища для списков

Первый и самый быстрый способ использования оператора *, который повторяет список указанных несколько раз.

>>> [None] * 10
[None, None, None, None, None, None, None, None, None, None]

Миллион итераций (значение итераций по умолчанию в timeit) занимает приблизительно 117 мс.

>>> timeit("[None] * 10")
0.11655918900214601

Другой подход - использование встроенной функции range с пониманием списка.

>>> [None for _ in range(10)]
[None, None, None, None, None, None, None, None, None, None]

Она почти в шесть раз медленнее и занимает 612 мс в секунду на миллион итераций.

>>> timeit("[None for _ in range(10)]")
0.6115895550028654

Третий подход - использование простого цикла for вместе с list.append().

>>> a = []
>>> for _ in range(10):
...   a.append(None)
...
>>> a
[None, None, None, None, None, None, None, None, None, None]

Использование циклов является самым медленным методом и занимает 842 мс на миллион итераций.

>>> timeit("for _ in range(10): a.append(None)", setup="a=[]")
0.8420009529945673

Предварительное выделение хранилища для других последовательных структур данных

Так как вы предварительно распределяете хранилище для последовательной структуры данных, то, возможно, имеет смысл использовать array встроенную структуру данных вместо списка.

>>> from array import array
>>> array('i',(0,)*10)
array('i', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

Как видно ниже, такой подход является вторым по скорости после [None] * 10.

>>> timeit("array('i',(0,)*10)", setup="from array import array")
0.4557597979946877

Сравним вышеприведенные подходы чистого Python с пакетом NumPy Python для научных вычислений.

>>> from numpy import empty
>>> empty(10)
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])

Путь NumPy занимает 589 мс на миллион итераций.

>>> timeit("empty(10)", setup="from numpy import empty")
0.5890094790011062

Однако, для более массивных списков путь NumPy будет намного быстрее.

>>> timeit("[None]*10000")
16.059584009999526
>>> timeit("empty(10000)", setup="from numpy import empty")
1.1065983309963485

Вывод в том, что для маленьких списков лучше придерживаться [None] * 10, но переключайтесь в NumPy’s empty() при работе с более массивными последовательными данными.

Сопутствующая статья - Python List

  • В чем разница между списочными методами добавлять и расширять
  • Как преобразовать список в струну на Python
  • Как соединить два или несколько списков на Python
  • В чем разница между делом, удалением и попаданием в списки Pythonа
  • Как быстро проверить, существует ли значение в списке Python
  • Как дублировать список на Python
  • Как сравнять списки на Python
  • comments powered by Disqus