2012-06-20 8 views
5

Sto costruendo una classe con tra gli altri un dizionario con chiavi intere e valori di lista. Aggiungere valori a questo dizionario sembra essere un vero e proprio collo di bottiglia e mi chiedevo se ci fosse un modo per velocizzare il mio codice.Python: ottimo modo di aggiungere al dizionario i valori di lista

class myClass(): 

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

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

Questo è davvero il modo ottimale per farlo? Non mi interessa davvero l'ordine dei valori, quindi forse c'è una struttura dati più adatta là fuori con un'app più veloce. Inoltre, "append" non sembra essere il problema principale, perché se aggiungo semplicemente a una lista vuota, il codice è molto più veloce. Immagino sia il caricamento della lista precedentemente memorizzata che occupa la maggior parte del tempo?


ho scoperto che il problema non è nel dizionario, ma nella lista append (anche se ho affermato tuttavia in mio post originale, per cui mi scuso). Questo problema è dovuto a un bug nel garbage collector di Python, che è ben spiegato su this other question. Disabilitare il gc prima di aggiungere tutti i valori e quindi riattivarlo, velocizza il processo immensamente!

+2

Aggiunta di elementi a un elenco e acquisizione di valori da un oggetto o un dettato non richiedono tempo. Per accelerare un programma, si trova il collo di bottiglia per profilazione, non modificando pezzi casuali di codice. –

+0

Gli elementi di mappatura alle chiavi esistenti sono notevolmente più veloci rispetto all'aggiunta di valori a nuove chiavi? –

+0

Ho appena scoperto che il problema non è nel dict, ma nella lista append (anche se ho affermato diversamente nel mio post originale, per il quale mi scuso). Poi ho trovato la risposta alla mia domanda su http://stackoverflow.com/questions/2473783/is-there-a-way-to-circumvent-python-list-append-becoming-progressively-slower. Dato che sono nuovo in questo sito, non so quale sia la procedura standard in questo caso: dovrei rimuovere il mio post originale? O aggiungere i dettagli sopra e rispondere al post? – niefpaarschoenen

risposta

0

Come conclusione posso dire che il mio codice nella domanda originale è più veloce o veloce di tutti gli altri suggerimenti.

2

confrontarlo con questo:

class myClass(): 

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

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

Per curiosità, perché è più veloce? Avrei pensato che "defaultdict" facesse qualcosa di molto simile dietro le quinte. –

+1

Dopo un breve test ho scoperto che non è più veloce. Mi piace solo meglio. – eumiro

+0

Penso che in realtà faccia lo stesso dietro le quinte; i tempi sono simili in ogni caso ... Io preferisco il defaultdict, però, perché in generale devi digitare di meno. – niefpaarschoenen

1

Dicono "Meglio chiedere perdono che il permesso.". Ora non stai chiedendo il permesso personalmente, ma ho pensato che forse lo fa defaultdict, ed è quello che lo rallenta.

try questo:

class myClass(): 

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

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

Questo tenta di accedere alla chiave index nel dizionario, se non esiste, alzerà un KeyError, e agire su di esso.

È più veloce?

+0

Ho provato a confrontare il codice e il codice dalla domanda (utilizzando [timeit] (http://docs.python.org/library/timeit.html)). Ho usato questo test: 'my = myClass() my.addValue (3," ab ") my.addValue (3," cd ") my.addValue (4," ef ") my.addValue (4, "gh") 'E il codice originale è più veloce! Sulla mia macchina 24,66 usec per il codice e 18.10 usec per il codice dalla domanda. Quindi sembra che questo approccio non sia la risposta .. – stalk

+1

Sembra che tu abbia la soluzione più veloce allora :) – jadkik94

Problemi correlati