HOWTO · Python
Cómo crear una lista con un tamaño específico en Python
Este tutorial muestra 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.