2012-06-20 11 views
5

Estoy creando una clase con un diccionario con claves enteras y valores de lista, entre otros. Sin embargo, agregar valores a este diccionario parece ser un cuello de botella real y me preguntaba si podría haber algún modo de acelerar mi código.Python: forma óptima de agregar al diccionario los valores de la lista

class myClass(): 

    def __init__(self): 
    self.d = defaultdict(list) 

    def addValue(self, index, value): 
    self.d[index].append(value) 

¿Es esta la mejor manera de hacerlo? Realmente no me importa el orden de los valores, así que tal vez haya una estructura de datos más adecuada con un apéndice más rápido. Por otra parte, 'append' no parece ser el problema principal, porque si simplemente anexo a una lista vacía, el código es mucho más rápido. Supongo que es la carga de la lista previamente almacenada la que ocupa la mayor parte del tiempo.


descubrí que el problema no está en el dict, pero en la lista de adición (a pesar de que se reivindique lo contrario en mi post original, por lo que pido disculpas). Este problema se debe a un error en el recolector de basura de Python, que está bien explicado en this other question. Desactivar el gc antes de agregar todos los valores y luego volver a habilitarlo, ¡acelera enormemente el proceso!

+2

Agregar elementos a una lista y obtener valores de un objeto o un dict no demoran nada. Para acelerar un programa, se encuentra el cuello de botella mediante el perfil, no cambiando piezas de código aleatorias. –

+0

¿Es mucho más rápido asignar elementos a claves existentes que agregar valores a claves nuevas? –

+0

Acabo de enterarme de que el problema no está en el dict, sino en la lista anexada (aunque afirmé lo contrario en mi publicación original, por la que me disculpo). Luego encontré la respuesta a mi pregunta en http://stackoverflow.com/questions/2473783/is-there-a-way-to-circumvent-python-list-append-becoming-progressively-slower. Como soy nuevo en este sitio, no sé cuál es el procedimiento estándar en este caso: ¿debo eliminar mi publicación original? ¿O agregar los detalles anteriores y responder a la publicación? – niefpaarschoenen

Respuesta

0

Como conclusión, puedo decir que mi código en la pregunta original es más rápido o más rápido que todas las demás sugerencias.

2

compararlo con esto:

class myClass(): 

    def __init__(self): 
    self.d = {} 

    def addValue(self, index, value): 
    self.d.setdefault(index, []).append(value) 
+1

Por curiosidad, ¿por qué es más rápido? Pensé que 'defaultdict' hace algo muy similar detrás de escena. –

+1

Después de una breve prueba descubrí que esto no es más rápido. Simplemente me gusta más. – eumiro

+0

Creo que en realidad hace lo mismo detrás de escena; los tiempos son similares en cualquier caso ... Aunque prefiero el default, porque en general debe escribir menos. – niefpaarschoenen

1

Dicen "Es mejor pedir perdón que permiso.". Ahora no estás pidiendo permiso personalmente, pero pensé que tal vez defaultdict sí, y eso es lo que ralentiza.

try esto:

class myClass(): 

    def __init__(self): 
    self.d = {} 

    def addValue(self, index, value): 
    try: 
     self.d[index].append(value) 
    except KeyError: 
     self.d[index] = [value] 

Este intenta acceder a la clave index en el diccionario, si no existe se levantará un KeyError, y actuar en consecuencia.

¿Es más rápido?

+0

He intentado comparar el código y el código de la pregunta (usando [timeit] (http://docs.python.org/library/timeit.html)). He utilizado esta prueba: 'my = myClass() my.addValue (3," ab ") my.addValue (3," cd ") my.addValue (4," ef ") my.addValue (4, "gh") '¡Y el código original es más rápido! En mi máquina 24.66 usec para su código y 18.10 usec para el código de la pregunta. Entonces parece que este enfoque no es la respuesta ... – stalk

+1

Parece que tienes la solución más rápida que :) – jadkik94

Cuestiones relacionadas