Ich habe versucht, unerwünschte Zeichen mit text.translate()
Python 3.4 aus einer bestimmten Zeichenfolge zu entfernen .
Der minimale Code lautet:
import sys
s = 'abcde12345@#@$#%$'
mapper = dict.fromkeys(i for i in range(sys.maxunicode) if chr(i) in '@#$')
print(s.translate(mapper))
Es funktioniert wie erwartet. Das gleiche Programm, wenn es in Python 3.4 und Python 3.5 ausgeführt wird, macht jedoch einen großen Unterschied.
Der Code zur Berechnung der Timings lautet
python3 -m timeit -s "import sys;s = 'abcde12345@#@$#%$'*1000 ; mapper = dict.fromkeys(i for i in range(sys.maxunicode) if chr(i) in '@#$'); " "s.translate(mapper)"
Das Python 3.4-Programm benötigt 1,3 ms, während das gleiche Programm in Python 3.5 nur 26,4 μs benötigt .
Was hat sich in Python 3.5 verbessert, das es im Vergleich zu Python 3.4 schneller macht?
python
string
python-3.x
python-internals
python-3.5
Bhargav Rao
quelle
quelle
dict.fromkeys(ord(c) for c in '@#$')
?Antworten:
TL; DR - AUSGABE 21118
Die lange Geschichte
Josh Rosenberg fand heraus, dass die
str.translate()
Funktion im Vergleich zu sehr langsambytes.translate
ist. Er warf ein Problem auf und erklärte:Warum war
str.translate()
langsam?Der Hauptgrund dafür
str.translate()
, sehr langsam zu sein, war, dass sich die Suche früher in einem Python-Wörterbuch befand.Die Verwendung von
maketrans
machte dieses Problem noch schlimmer. Bei einem ähnlichen Ansatz wirdbytes
ein C-Array mit 256 Elementen erstellt, um eine schnelle Tabellensuche zu ermöglichen. Daher macht die Verwendung von höherstufigem Pythondict
dasstr.translate()
in Python 3.4 sehr langsam.Was ist gerade passiert?
Der erste Ansatz bestand darin, einen kleinen Patch, translate_writer , hinzuzufügen. Die Geschwindigkeitssteigerung war jedoch nicht so erfreulich. Bald wurde ein weiterer Patch fast_translate getestet, der sehr gute Ergebnisse mit einer Beschleunigung von bis zu 55% lieferte.
Die wichtigste Änderung, die aus der Datei hervorgeht, besteht darin, dass die Python-Wörterbuchsuche in eine C-Level-Suche geändert wird.
Die Geschwindigkeiten sind jetzt fast die gleichen wie
bytes
Eine kleine Anmerkung hier ist, dass die Leistungsverbesserung nur in ASCII-Zeichenfolgen prominent ist.
Wie JFSebastian in einem Kommentar unten erwähnt, funktioniert Übersetzen vor 3.5 in ASCII- und Nicht-ASCII-Fällen auf dieselbe Weise. Ab 3.5 ASCII ist der Fall jedoch viel schneller.
Früher waren ASCII und Nicht-ASCII fast gleich, jetzt können wir jedoch eine große Veränderung in der Leistung feststellen.
Dies kann eine Verbesserung von 71,6 μs auf 2,33 μs sein, wie in dieser Antwort gezeigt .
Der folgende Code demonstriert dies
Tabelle der Ergebnisse:
quelle
55
%: Wie Ihre Antwort zeigt, kann die Beschleunigung1000
s% betragen .python3.5 -m timeit -s "text = 'mJssissippi'*100; d=dict(J='i')" "text.translate(d)"
(ASCII) vs.python3.5 -m timeit -s "text = 'm\U0001F602ssissippi'*100; d={'\U0001F602': 'i'}" "text.translate(d)"
(Nicht-ASCII). Letzteres ist viel (10x) langsamer..translate()
dh, Ascii -Fälle sind nur in Python 3.5 viel schneller (Sie benötigen dort keinebytes.translate()
Leistung).