2012-06-22 1 views
19

Auf diesem page, sehe ich etwas Interessantes:Ist es immer schneller, String als Schlüssel in einem Diktat zu verwenden?

Hinweis, dass es ein schneller Weg für dicts ist, dass (in der Praxis) nur mit str Tasten beschäftigen; Dies beeinflusst die algorithmische Komplexität nicht, aber es kann die konstanten Faktoren signifikant beeinflussen: wie schnell ein typisches Programm endet.

Also was genau bedeutet es?

Bedeutet es die Verwendung von Zeichenfolge, da der Schlüssel immer schneller ist?

Wenn ja, warum?

Update:

Danke für die Vorschläge über die Optimierung! Aber eigentlich interessiere ich mich mehr für die reine Wahrheit, als ob oder wann wir optimieren sollten.

Update 2:

Vielen Dank für die tolle Antworten, werde ich den Inhalt aus dem von @DaveWebb bereitgestellt link zitieren hier:

" ...

ma_lookup ist zunächst auf die lookdict_string Funktion eingestellt (umbenannt in lookdict_unicode in 3.0), die als Es wird angenommen, dass sowohl die Schlüssel im Wörterbuch als auch der gesuchte Schlüssel Standard-PyStringObject sind. Es ist dann in der Lage, einige Optimierungen vorzunehmen, beispielsweise verschiedene Fehlerprüfungen zu mildern, da der String-zu-String-Vergleich niemals Ausnahmen auslöst. Es gibt auch keine Notwendigkeit für reiche Objektvergleiche, was bedeutet, dass wir den Aufruf von PyObject_RichCompareBool vermeiden und immer _PyString_Eq direkt verwenden.

... "

Auch für die Versuchsnummern, ich glaube, die Größe der Differenz wird noch größer, wenn es keine int-to-String Umwandlung

+2

Ich würde vermuten, dass alles darauf ankommt, wie schnell die '__hash__' Methode eines Schlüsselobjekts ist. Ich nehme an, dass es ziemlich einfach ist, eine Zeichenkette zu hashen, aber ich würde mich sehr dafür interessieren, wie viel Anteil einer Wörterbuchsuche ausgegeben wird. – Wilduck

+0

Ihr Update ändert nichts. Nein, es wird in den meisten Fällen nicht schneller sein, es sei denn, deine Schlüssel waren ursprünglich Zeichenfolgen. –

+0

@Lattyware die verknüpfte Seite scheint eine Erhöhung der Geschwindigkeit * für jede Suche * nicht nur für die Konstruktion zu implizieren. – Wilduck

Antwort

17

Der C-Code, der dem Python-Dict zugrunde liegt, wird für String-Schlüssel optimiert. You can read about this here (und in dem Buch bezieht sich der Blog).

Wenn die Python-Laufzeitumgebung weiß, dass Ihr dict nur Zeichenfolgenschlüssel enthält, kann sie beispielsweise Fehler nicht berücksichtigen, die bei einem Zeichenfolgenvergleich auftreten, und die Rich-Vergleichsoperatoren ignorieren. Dies wird den allgemeinen Fall des String-Schlüssels nur dict ein wenig schneller machen. (Update: Timing zeigt, dass es mehr als ein wenig ist.)

Es ist jedoch unwahrscheinlich, dass dies eine signifikante Änderung der Laufzeit der meisten Python-Programme würde. Sorgen Sie sich nur um diese Optimierung, wenn Sie dict Lookups als Engpass in Ihrem Code gemessen und gefunden haben. As the famous quote says, "Premature optimization is the root of all evil."

Der einzige Weg, um zu sehen, wie viel schneller die Dinge wirklich sind, ist es, sie Zeit:

>>> timeit.timeit('a["500"]','a ={}\nfor i in range(1000): a[str(i)] = i') 
0.06659698486328125 
>>> timeit.timeit('a[500]','a ={}\nfor i in range(1000): a[i] = i') 
0.09005999565124512 

Also mit String-Schlüssel ist ca. 30% schneller sogar im Vergleich zu int Tasten, und ich habe mich zugeben, war überrascht über die Größe des Unterschieds.

+0

Ihr Test geht davon aus, dass es keine Kosten für "500" im Gegensatz zu "500" gibt - was einen großen Unterschied macht - siehe meine Antwort. –

+1

Die Frage, ob String-Schlüssel immer schneller waren und mein Test zeigen sollte, was es getan hat. Ich glaube nicht, dass die Frage war, von einem anderen Objekt in einen String zu konvertieren und diesen als Schlüssel zu verwenden - was aus einer Reihe von Gründen schlecht wäre - sondern einfach, wenn es immer sinnvoll war, Strings zu verwenden, wenn die Auswahl verfügbar war. –

+0

Das bringt es aus dem Zusammenhang. Es ist sinnlos, zu wissen, dass es schneller ist, Zeichenfolgenschlüssel zu verwenden, wenn dann die Zeichenfolgenschlüssel langsamer werden. –

8

Da dies nur die Affekte Wenn Sie mit sehr großen Datensätzen arbeiten, brauchen Sie diese Zeit nur wirklich zu optimieren - was nichts anbelangt.

Was das bedeutet, ist das in den Fällen wo Sie kleine Wörterbücher mit Strings als Schlüssel haben, wird Python schnell sein - das ist eine übliche Verwendung es wurde für optimiert.

Wie Ignacio Vazquez-Abrams hervorhebt, ist es wahrscheinlich, dass die Umwandlung Ihres Schlüssels in eine Saite (weit) mehr kostet als die leichte Steigerung, die Sie daraus ziehen können, dass sie eine Saite für das Diktat ist.

Kurz gesagt, was für Ihre Situation relevant ist - die Optimierung sollte nur dort durchgeführt werden, wo Bedarf besteht, nicht vorher.

Einige Tests:

python -m timeit -s "a={key: 1 for key in range(1000)}" "a[500]" 
10000000 loops, best of 3: 0.0773 usec per loop 

python -m timeit -s "a={str(key): 1 for key in range(1000)}" "a[\"500\"]" 
10000000 loops, best of 3: 0.0452 usec per loop 

python -m timeit -s "a={str(key): 1 for key in range(1000)}" "a[str(500)]" 
1000000 loops, best of 3: 0.244 usec per loop 

Wie Sie sehen können, während der String-basierte dict schneller ist, ist der Schlüssel Umwandlung im Vergleich sehr teuer, völlig die Verstärkung zu mildern (und dann einige).

Also ja, wenn die Daten, die Sie verwenden ist nur als Schlüssel zum Wörterbuch verwendet wird, und welches Format Ihr Geschäft sie in keine Rolle spielt, dann Saiten bevorzugt, in einem kleinen Wörterbuch. In der Praxis ist das ein sehr seltener Fall (und Sie würden wahrscheinlich bereits Strings verwenden).

+4

Besonders, da die Umwandlung einiger Typen in eine Zeichenfolge teurer als nur die Verwendung als Schlüssel ist. –

+0

Entschuldigung, ich denke, ich sollte meine Frage ändern – xvatar

+0

@ IgnacioVazquez-Abrams Sehr wahr. –

Verwandte Themen