punteros objetos objeto memoria manejo maneja eliminar dinámica destruir como asignación python performance arrays memory-management list

objetos - punteros en python



¿Reserva memoria para la lista en Python? (6)

Aquí hay cuatro variantes:

  • una creación de lista incremental
  • lista "preasignada"
  • array.array ()
  • numpy.zeros ()

python -mtimeit -s"N=10**6" "a = []; app = a.append;"/ "for i in xrange(N): app(i);" 10 loops, best of 3: 390 msec per loop python -mtimeit -s"N=10**6" "a = [None]*N; app = a.append;"/ "for i in xrange(N): a[i] = i" 10 loops, best of 3: 245 msec per loop python -mtimeit -s"from array import array; N=10**6" "a = array(''i'', [0]*N)"/ "for i in xrange(N):" " a[i] = i" 10 loops, best of 3: 541 msec per loop python -mtimeit -s"from numpy import zeros; N=10**6" "a = zeros(N,dtype=''i'')"/ "for i in xrange(N):" " a[i] = i" 10 loops, best of 3: 353 msec per loop

Muestra que [None]*N es el más rápido y array.array es el más lento en este caso.

Cuando se programa en Python, ¿es posible reservar memoria para una lista que se completará con un número conocido de elementos, de modo que la lista no se reasigne varias veces al construirla? He buscado en los documentos un tipo de lista de Python, y no he encontrado nada que parezca hacer esto. Sin embargo, este tipo de creación de listas se muestra en algunas zonas activas de mi código, por lo que quiero que sea lo más eficiente posible.

Editar: Además, ¿tiene sentido hacer algo como esto en un lenguaje como Python? Soy un programador bastante experimentado, pero nuevo en Python y todavía estoy sintiendo su forma de hacer las cosas. ¿Python asigna internamente todos los objetos en espacios de montón separados, derrotando el propósito de tratar de minimizar las asignaciones, o son primitivas como entradas, flotantes, etc. almacenados directamente en listas?


En Python, todos los objetos se asignan en el montón.
Pero Python usa un asignador de memoria especial para que no se malloc cada vez que necesite un objeto nuevo.
También hay algunas optimizaciones para enteros pequeños (y similares) que se almacenan en caché; sin embargo, qué tipos y cómo depende la implementación.


En la mayoría del código diario, no necesitará dicha optimización.

Sin embargo, cuando la eficacia de la lista se convierte en un problema, lo primero que debe hacer es reemplazar la lista genérica con una escrita a máquina del módulo de array , que es mucho más eficiente.

Así es como se creará la lista de 4 millones de números de coma flotante:

import array lst = array.array(''f'', [0.0]*4000*1000)


Mira esto:

In [7]: %timeit array.array(''f'', [0.0]*4000*1000) 1 loops, best of 3: 306 ms per loop In [8]: %timeit array.array(''f'', [0.0])*4000*1000 100 loops, best of 3: 5.96 ms per loop In [11]: %timeit np.zeros(4000*1000, dtype=''f'') 100 loops, best of 3: 6.04 ms per loop In [9]: %timeit [0.0]*4000*1000 10 loops, best of 3: 32.4 ms per loop

Así que nunca use array.array(''f'', [0.0]*N) , use array.array(''f'', [0.0])*N o numpy.zeros .


Si quiere manipular los números de manera eficiente en Python, eche un vistazo a NumPy ( http://numpy.scipy.org/ ). Te permite hacer cosas extremadamente rápido mientras usas Python.

Para hacer lo que preguntas en NumPy, harías algo como

import numpy as np myarray = np.zeros(4000)

que le daría una matriz de números de coma flotante inicializados a cero. A continuación, puedes hacer cosas geniales como matrices multiplas completas por un solo factor o por otras matrices y otras cosas (algo así como en Matlab si alguna vez has usado eso) que es muy rápido (la mayor parte del trabajo real está sucediendo en el parte C altamente optimizada de la biblioteca NumPy).

Si no se trata de matrices de números, entonces es probable que no encuentres la manera de hacer lo que quieres en Python. Una lista de objetos de Python es una lista de puntos a objetos internamente (creo que sí, no soy un experto de Python en el interior) por lo que seguiría asignando cada uno de sus miembros a medida que los creas.


puede crear una lista de la longitud conocida como esta:

>>> [None] * known_number