2009-03-17 7 views
10

Zuerst bin ich neu bei Python, also entschuldige ich mich, wenn ich etwas übersehen habe, aber ich möchte dict.fromkeys (oder etwas Ähnliches) verwenden, um ein Wörterbuch mit Listen zu erstellen, deren Schlüssel in einer anderen Liste enthalten sind. Ich habe einige Timing-Tests durchführen, und ich möchte für den Schlüssel die Eingangsgröße und die Liste sein, die Zeiten für die Läufe enthalten:Wie erstelle ich einen eindeutigen Wert für jeden Schlüssel mit dict.fromkeys?

def benchmark(input): 
    ... 
    return time_taken 

runs = 10 
inputs = (1, 2, 3, 5, 8, 13, 21, 34, 55) 
results = dict.fromkeys(inputs, []) 

for run in range(0, runs): 
    for i in inputs: 
     results[i].append(benchmark(i)) 

Das Problem, das ich habe, ist, dass alle Schlüssel in Das Wörterbuch scheint dieselbe Liste zu haben, und jeder Lauf hängt einfach daran. Gibt es eine Möglichkeit, eine eindeutige leere Liste für jeden Schlüssel mit fromkeys zu generieren? Wenn nicht, gibt es einen anderen Weg, dies zu tun, ohne das resultierende Wörterbuch von Hand zu erzeugen?

Antwort

10

Das Problem ist, dass in

results = dict.fromkeys(inputs, []) 

[] nur einmal ausgewertet wird, genau dort.

ich diesen Code so umschreiben würde:

runs = 10 
inputs = (1, 2, 3, 5, 8, 13, 21, 34, 55) 
results = {} 

for run in range(runs): 
    for i in inputs: 
     results.setdefault(i,[]).append(benchmark(i)) 

Andere Option ist:

runs = 10 
inputs = (1, 2, 3, 5, 8, 13, 21, 34, 55) 
results = dict([(i,[]) for i in inputs]) 

for run in range(runs): 
    for i in inputs: 
     results[i].append(benchmark(i)) 
+0

Ehrfürchtig, das funktioniert gut! Vielen Dank! (obwohl ich wünschte, es wäre möglich, die leeren Listen zu generieren, bevor ich sie verwenden musste) –

+0

Es ist nicht möglich. Sobald Sie [] oder list() aufrufen, wird ein Objekt erstellt und die Variable gebunden. Schau dir das mal an x ​​= [[]] * 10; x [0] .app (Test); print x – vartec

+0

Ok, da gibt es Alternativen mit allen instanziierten Listen. – vartec

12

Überprüfen Sie defaultdict (erfordert Python 2.5 oder höher).

from collections import defaultdict 

def benchmark(input): 
    ... 
    return time_taken 

runs = 10 
inputs = (1, 2, 3, 5, 8, 13, 21, 34, 55) 
results = defaultdict(list) # Creates a dict where the default value for any key is an empty list 

for run in range(0, runs): 
    for i in inputs: 
     results[i].append(benchmark(i)) 
+0

Das funktioniert auch gut - ich wünschte nur, es wäre ein "echtes" Wörterbuch, keine Klasse, die vorgibt, eine zu sein. –

+0

Um fair zu sein, es ist eine Unterklasse mit sehr minimalen Änderungen, so "vorgibt, eins zu sein" scheint ein bisschen stark. –

+0

+1 Es ist der Weg, es zu tun, wenn Sie sicher sind, dass Sie Ihren Code nicht mit Python <2.5 verwenden müssen. (Vor kurzem habe ich Hosting-Angebote nachgeschlagen, und es gibt immer noch eine Menge Python 2.4). – vartec

2

Sie können dies auch tun, wenn Sie nicht wollen, etwas Neues lernen (obwohl ich empfehlen tust du!) Ich bin gespannt, welche Methode schneller ist?

results = dict.fromkeys(inputs) 

for run in range(0, runs): 
    for i in inputs: 
     if not results[i]: 
      results[i] = [] 
     results[i].append(benchmark(i)) 
Verwandte Themen