Cómo crear una lista con un tamaño específico en Python

Jinku Hu 30 enero 2023
  1. Preasignación de almacenamiento para listas
  2. Preasignación de almacenamiento para otras estructuras de datos secuenciales
Cómo crear una lista con un tamaño específico en Python

La preasignación de almacenamiento para listas o arrays es un patrón típico entre los programadores
cuando saben el número de elementos con antelación.

A diferencia de C++ y Java, en Python hay que inicializar todo el almacenamiento preasignado con algunos valores.
Normalmente, los desarrolladores usan valores falsos para ese propósito, como None, False, y 0.

Python ofrece varias maneras de crear una lista de un tamaño fijo, cada una con
diferentes características de rendimiento.

Para comparar el rendimiento de los diferentes enfoques, utilizaremos el estándar de Python
módulo timeit.
Proporciona una forma práctica de medir los tiempos de ejecución de pequeños trozos de código Python.

Preasignación de almacenamiento para listas

La primera y más rápida manera de usar el operador *, que repite una lista una vez especificada
número de veces.

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

Un millón de iteraciones (valor por defecto de las iteraciones en timeit) toman aproximadamente
117 ms.

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

Otra aproximación es usar la función incorporada range con una comprensión de la lista.

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

Es casi seis veces más lenta y tarda 612 ms segundo por millón de iteraciones.

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

La tercera aproximación es usar un bucle simple for junto con el list.append().

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

El uso de bucles es el método más lento y toma 842 ms para completar un millón de iteraciones.

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

Preasignación de almacenamiento para otras estructuras de datos secuenciales

Dado que está preasignando almacenamiento para una estructura de datos secuencial, puede tener mucho sentido utilizar la estructura de datos incorporada en array en lugar de una lista.

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

Como vemos a continuación, este enfoque es el segundo más rápido después de [None] * 10.

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

Comparemos las aproximaciones a Python puro de arriba con el paquete Python NumPy para computación científica.

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

El camino de NumPy toma 589 ms por millón de iteraciones.

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

Sin embargo, el camino de NumPy será mucho más rápido para listas más masivas.

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

La conclusión es que es mejor atenerse a None * 10 para listas pequeñas, pero cambiar
al empty() de NumPy cuando se trata de datos secuenciales más masivos.

Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Artículo relacionado - Python List