python performance - Was ist eine schnellere Operation, re.match / search oder str.find?





vs java (5)


Die Frage: timeit schneller ist, wird am besten mit timeit beantwortet.

from timeit import timeit
import re

def find(string, text):
    if string.find(text) > -1:
        pass

def re_find(string, text):
    if re.match(text, string):
        pass

def best_find(string, text):
    if text in string:
       pass

print timeit("find(string, text)", "from __main__ import find; string='lookforme'; text='look'")  
print timeit("re_find(string, text)", "from __main__ import re_find; string='lookforme'; text='look'")  
print timeit("best_find(string, text)", "from __main__ import best_find; string='lookforme'; text='look'")  

Die Ausgabe ist:

0.441393852234
2.12302494049
0.251421928406

Sie sollten also nicht nur den in Operator verwenden, weil er einfacher zu lesen ist, sondern auch weil er schneller ist.

Ist es bei einer Suche nach einem String einfacher, einfach str.find / rfind zu verwenden, als re.match / search zu verwenden?

Das heißt, für eine gegebene Zeichenfolge, s, sollte ich Folgendes verwenden:

if s.find('lookforme') > -1:
    do something

oder

if re.match('lookforme',s):
    do something else

?




Ich hatte das gleiche Problem. Ich habe Jupyters% Zeit verwendet, um zu überprüfen:

import re
sent = "a sentence for measuring a find function"
sent_list = sent.split()
print("x in sentence")
%timeit "function" in sent
print("x in token list")
%timeit "function" in sent_list

print("regex search")
%timeit bool(re.match(".*function.*", sent))
print("compiled regex search")
regex = re.compile(".*function.*")
%timeit bool(regex.match(sent))

x in Satz 61.3 ns ± 3 ns pro Schleife (Mittelwert ± Standardabweichung von 7 Läufen, jeweils 10000000 Schleifen)

x in Token-Liste 93,3 ns ± 1,26 ns pro Schleife (Mittelwert ± Std. Dev. von 7 Läufen, jeweils 10000000 Schleifen)

Regex-Suche 772 ns ± 8,42 ns pro Schleife (Mittelwert ± Std. Dev. von 7 Läufen, jeweils 1000000 Schleifen)

kompilierte Regex-Suche 420 ns ± 7.68 ns pro Schleife (Mittelwert ± Std. Dev. von 7 Läufen, jeweils 1000000 Schleifen)

Kompilieren ist schnell, aber das Einfache ist besser.




Benutze das:

if 'lookforme' in s:
    do something

Regex muss zuerst kompiliert werden, was zusätzlichen Aufwand verursacht. Pythons normale String-Suche ist sowieso sehr effizient.

Wenn Sie den gleichen Begriff viel suchen oder wenn Sie etwas Komplexeres tun, dann wird Regex nützlicher.




re.compile beschleunigt Regexs viel, wenn Sie immer wieder nach dem gleichen Ding suchen. Aber ich habe gerade eine große Beschleunigung bekommen, indem ich "in" benutzt habe, um schlechte Fälle auszusortieren, bevor ich mich anmelde. Anekdotisch, ich weiß. ~ Ben




Für Fließkomma-Code kann der <= Vergleich tatsächlich sogar auf modernen Architekturen langsamer sein (durch einen Befehl). Hier ist die erste Funktion:

int compare_strict(double a, double b) { return a < b; }

Auf PowerPC führt dies zuerst einen Gleitkommavergleich durch (der cr aktualisiert, das Bedingungsregister), verschiebt dann das Bedingungsregister zu einem GPR, verschiebt das Bit "verglichen mit weniger als" an Stelle und kehrt dann zurück. Es dauert vier Anweisungen.

Betrachten Sie stattdessen diese Funktion:

int compare_loose(double a, double b) { return a <= b; }

Dies erfordert die gleiche Arbeit wie compare_strict oben, aber jetzt gibt es zwei Bits von Interesse: "war weniger als" und "war gleich". Dies erfordert eine zusätzliche Anweisung ( cror - Bedingungsregister bitweise ODER), um diese beiden Bits zu einem zu kombinieren. So benötigt compare_loose fünf Anweisungen, während compare_strict vier erfordert.

Sie könnten denken, dass der Compiler die zweite Funktion wie folgt optimieren könnte:

int compare_loose(double a, double b) { return ! (a > b); }

Dies wird jedoch nicht korrekt mit NaNs umgehen. NaN1 <= NaN2 und NaN1 > NaN2 müssen beide zu falsch auswerten.







python performance