sumar - metodos de listas en python
Inicializando una lista a un nĂºmero conocido de elementos en Python (9)
Esta pregunta ya tiene una respuesta aquí:
- Crear una lista vacía en python con cierto tamaño 14 respuestas
En este momento estoy usando una lista, y esperaba algo como:
verts = list (1000)
¿Debo usar array en su lugar?
@Steve ya dio una buena respuesta a tu pregunta:
verts = [None] * 1000
Advertencia: como señaló @Joachim Wuttke, la lista debe inicializarse con un elemento inmutable. [[]] * 1000
no funciona como se esperaba porque obtendrás una lista de 1000 listas idénticas (similar a una lista de 1000 puntos de la misma lista en C). Los objetos inmutables como int, str o tuple estarán bien.
Alternativas
Cambiar el tamaño de las listas es lento. Los siguientes resultados no son muy sorprendentes:
>>> N = 10**6
>>> %timeit a = [None] * N
100 loops, best of 3: 7.41 ms per loop
>>> %timeit a = [None for x in xrange(N)]
10 loops, best of 3: 30 ms per loop
>>> %timeit a = [None for x in range(N)]
10 loops, best of 3: 67.7 ms per loop
>>> a = []
>>> %timeit for x in xrange(N): a.append(None)
10 loops, best of 3: 85.6 ms per loop
Pero el cambio de tamaño no es muy lento si no tienes listas muy grandes. En lugar de inicializar la lista con un solo elemento (por ejemplo, None
) y una longitud fija para evitar el cambio de tamaño de la lista, debe considerar el uso de la lista de comprensión y llenar directamente la lista con los valores correctos. Por ejemplo:
>>> %timeit a = [x**2 for x in xrange(N)]
10 loops, best of 3: 109 ms per loop
>>> def fill_list1():
"""Not too bad, but complicated code"""
a = [None] * N
for x in xrange(N):
a[x] = x**2
>>> %timeit fill_list1()
10 loops, best of 3: 126 ms per loop
>>> def fill_list2():
"""This is slow, use only for small lists"""
a = []
for x in xrange(N):
a.append(x**2)
>>> %timeit fill_list2()
10 loops, best of 3: 177 ms per loop
Comparacion con numpy
Para grandes conjuntos de datos, numpy u otras bibliotecas optimizadas son mucho más rápidas:
from numpy import ndarray, zeros
%timeit empty((N,))
1000000 loops, best of 3: 788 ns per loop
%timeit zeros((N,))
100 loops, best of 3: 3.56 ms per loop
Debería considerar usar un tipo dict
lugar de una lista preinicializada. El costo de una búsqueda en el diccionario es pequeño y comparable al costo de acceder a un elemento de lista arbitrario.
Y cuando usas un mapeo puedes escribir:
aDict = {}
aDict[100] = fetchElement()
putElement(fetchElement(), fetchPosition(), aDict)
Y la función putElement
puede almacenar el artículo en cualquier posición dada. Y si necesita comprobar si su colección contiene un elemento en el índice dado, es más Pythonic escribir:
if anIndex in aDict:
print "cool!"
Que:
if not myList[anIndex] is None:
print "cool!"
Dado que este último asume que ningún elemento real en su colección puede ser None
. Y si eso sucede, tu código se comporta mal.
Y si necesita un rendimiento desesperado y es por eso que intenta preinicializar sus variables y escribir el código más rápido posible, cambie su idioma. El código más rápido no se puede escribir en Python. En su lugar, debería probar C e implementar envoltorios para llamar a su código preinicializado y precompilado desde Python.
Esta:
lst = [8 for i in range(9)]
Crea una lista, los elementos se inicializan 8.
pero esto:
lst = [0] * 7
crearía 7 listas que tienen un elemento
Lo primero que me viene a la mente es:
verts = [None]*1000
¿Pero realmente necesitas preinicializarlo?
No estoy seguro de por qué todo el mundo le está dando un mal momento para querer hacer esto; hay varios escenarios en los que querría una lista inicializada de tamaño fijo. Y has deducido correctamente que los arreglos son sensibles en estos casos.
import array
verts=array.array(''i'',(0,)*1000)
Para los no-pythonistas, el término (0,)*1000
está creando una tupla que contiene 1000 ceros. La coma obliga a Python a reconocer (0)
como una tupla, de lo contrario se evaluaría como 0.
He usado una tupla en lugar de una lista porque generalmente tienen menos gastos generales.
Podrías hacer esto:
verts = list(xrange(1000))
Eso le daría una lista de 1000 elementos en tamaño y que se inicializará con valores de 0-999. Como la list
hace un __len__
primero para dimensionar la nueva lista, debería ser bastante eficiente.
Querer inicializar una matriz de tamaño fijo es algo perfectamente aceptable en cualquier lenguaje de programación; no es como si el programador quisiera poner una instrucción break en un bucle while (true). Créanme, especialmente si los elementos solo se sobrescribirán y no simplemente se agregarán / restarán, como es el caso de muchos algoritmos de programación dinámica, no desea perder el tiempo con las declaraciones adjuntas y verificar si el elemento no ha sido Inicializado aún sobre la marcha (eso es un montón de código de hombres).
object = [0 for x in range(1000)]
Esto funcionará para lo que el programador está tratando de lograr.
Sin saber más sobre el dominio del problema, es difícil responder a su pregunta. A menos que esté seguro de que necesita hacer algo más, la forma pitónica de inicializar una lista es:
verts = []
¿Estás viendo realmente un problema de rendimiento? Si es así, ¿cuál es el cuello de botella de rendimiento? No trates de resolver un problema que no tienes. Es probable que el costo de rendimiento para llenar dinámicamente una matriz de 1000 elementos sea completamente irrelevante para el programa que realmente está intentando escribir.
La clase de matriz es útil si las cosas en su lista siempre van a ser un tipo de longitud fija primitiva específica (por ejemplo, char, int, float). Pero, tampoco requiere preinicialización.
Una forma obvia y probablemente no eficiente es
verts = [0 for x in range(1000)]
Tenga en cuenta que esto puede extenderse a 2 dimensiones fácilmente. Por ejemplo, para obtener una "matriz" de 10x100 puede hacer
verts = [[0 for x in range(100)] for y in range(10)]