Lohnt es sich Pythons re.compile zu verwenden?
Gibt es Vorteil bei der Verwendung kompilieren für reguläre Ausdrücke in Python?
h = re.compile('hello')
h.match('hello world')
vs
re.match('hello', 'hello world')
InformationsquelleAutor der Frage Mat | 2009-01-16
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich habe eine Menge Erfahrung in der Leitung einer kompilierten regex 1000 mal gegen das kompilieren " on-the-fly, und habe nicht bemerkt, jede wahrnehmbare Unterschied. Offensichtlich, dies ist anekdotisch, und sicherlich nicht ein tolles argument gegen kompilieren, aber ich habe festgestellt, das der Unterschied zu vernachlässigen sein.
BEARBEITEN:
Nach einem kurzen Blick auf die aktuelle Python 2.5 library code, sehe ich, dass Python intern kompiliert UND ZWISCHENGESPEICHERT regexes immer dann, wenn Sie Sie sowieso (einschließlich Anrufe bei
re.match()
), du bist also wirklich nur ändern, WENN der reguläre Ausdruck kompiliert wird, und sollte nicht viel Zeit einzusparen überhaupt - nur die Zeit, die es braucht, um den cache prüfen (ein-Schlüssel-lookup auf eine internedict
- Typ).Vom Modul re.py (Kommentare sind von mir):
Ich noch oft vor-kompilieren von regulären Ausdrücken, aber nur, um Sie zu binden, um eine schöne, wiederverwendbare Namen, nicht für die erwartete Leistung zu gewinnen.
InformationsquelleAutor der Antwort Triptych
Für mich der größte Vorteil für
re.compile
ist nicht jede Art der vorzeitigen Optimierung (das ist die Wurzel allen übelstrotzdem). Es können separate definition des regex von seiner Verwendung.Schon ein einfacher Ausdruck wie
0|[1-9][0-9]*
(ganze Zahl in der Basis 10 ohne führende Nullen) werden kann, Komplex genug, dass Sie lieber nicht haben, um erneut eingeben, prüfen Sie, ob Sie keine Tippfehler gemacht, und später haben Sie noch einmal überprüfen, wenn es gibt Tippfehler, wenn Sie mit dem Debuggen beginnen. Plus, es ist schöner zu verwenden, eine variable Namen, wie num oder num_b10 als0|[1-9][0-9]*
.Es ist sicherlich möglich, um Zeichenfolgen zu speichern und geben Sie Sie wieder.übereinstimmen; jedoch, das ist weniger lesbar:
Versus kompilieren:
Aber es ist ziemlich nah, die Letzte Zeile des zweiten, fühlt sich viel natürlicher und einfacher, wenn wiederholt verwendet.
InformationsquelleAutor der Antwort
FWIW:
so, wenn du gehst, werden mithilfe der gleichen regex viel, kann es sich lohnen, es zu tun
re.compile
(insbesondere bei komplexeren regexes).Die standard-Argumente gegen die vorzeitige Optimierung anwenden, aber ich glaube nicht, dass Sie wirklich verlieren viel Klarheit/Eindeutigkeit durch die Verwendung von
re.compile
wenn Sie vermuten, dass Ihr regexps kann zu einem performance-Engpass.InformationsquelleAutor der Antwort dF.
Hier ist ein einfacher Testfall:
mit re.kompilieren:
So, es scheint zu kompilieren ist schneller mit diesem einfachen Fall auch wenn Sie nur einmal.
InformationsquelleAutor der Antwort david king
Ich habe gerade versucht diese selbst. Für den einfachen Fall der Analyse einer Zahl aus einem string und addieren es, die Verwendung einer kompilierten regulären Ausdruck Objekt ist etwa doppelt so schnell sein wie der
re
Methoden.Als andere haben darauf hingewiesen, dass der
re
Methoden (einschließlichre.compile
) schauen den regulären Ausdruck in einen cache von bereits kompilierten Ausdrücke. Also im normal Fall werden die zusätzlichen Kosten für die Nutzung derre
Methoden ist einfach die Kosten für die cache-Suche.Jedoch, die Prüfung der codezeigt der cache ist auf 100 beschränkt Ausdrücken. Dies wirft die Frage auf, wie schmerzhaft ist es zu einem überlauf der cache? Der code enthält einen internen interface, um den regulären Ausdruck, compiler,
re.sre_compile.compile
. Wenn wir es nennen, wir der cache umgangen. Es stellt sich heraus, dass etwa zwei Größenordnungen langsamer für einen einfachen regulären Ausdruck, wier'\w+\s+([0-9_]+)\s+\w*'
.Hier mein test:
'ReallyCompiled' Methoden verwenden Sie die interne Schnittstelle, das umgeht den cache. Beachten Sie die eine, die kompiliert auf jeder loop-iteration wird nur iteriert 10.000 mal, nicht eine million.
InformationsquelleAutor der Antwort George
Stimme ich mit Honest Abe, der
match(...)
in den gegebenen Beispielen unterschiedlich sind. Sie sind nicht eine eins-zu-eins-Vergleiche und somit die Ergebnisse sind unterschiedlich. Zur Vereinfachung meiner Antwort, die ich verwenden A, B, C, D für diese Funktionen in Frage. Oh ja, wir beschäftigen uns mit 4 Funktionen inre.py
statt 3.Läuft dieses Stück code:
ist die gleiche wie dieser code ausgeführt:
Weil, wenn sah in die Quelle
re.py
(A + B) bedeutet:und (C) tatsächlich:
So, (C) ist nicht dasselbe wie (B). In der Tat, (C) ruft (B) nach dem Aufruf (D), die auch als durch (Eine). In anderen Worten,
(C) = (A) + (B)
. Daher vergleicht man (A + B) innerhalb einer Schleife hat das gleiche Ergebnis, wie (C) in einer Schleife.George ' s
regexTest.py
erwies sich dies für uns.Jedermanns Interesse ist, wie man das Ergebnis von 2.323 Sekunden. Um sicherzustellen, dass
compile(...)
bekommen nur einmal aufgerufen, wir müssen zum speichern der kompilierten regex-Objekt im Speicher. Wenn wir über eine Klasse, könnten wir das Objekt gespeichert werden soll, und wiederverwenden, wenn jedes mal, wenn unsere Funktion aufgerufen.Wenn wir nicht über die Klasse (das ist mein Wunsch heute), dann habe ich kein Kommentar. Ich bin immer noch lernen, mit globalen Variablen in Python, und ich weiß, Globale variable ist eine schlechte Sache.
Einen Punkt mehr, ich glaube, dass mit
(A) + (B)
Ansatz hat die Oberhand. Hier sind einige Fakten, die ich beobachtet habe (bitte korrigieren Sie mich, wenn ich falsch Liege):Fordert Eine einmal, es wird eine Suche in der
_cache
gefolgt von einemsre_compile.compile()
zum erstellen eines regex-Objekts. Ruft Ein zweimal, es wird zwei sucht und man kompilieren (weil die regex-Objekt wird zwischengespeichert).Wenn die
_cache
geleert erhalten in zwischen, dann das regex-Objekt wird aus dem Speicher freigegeben und Python müssen erneut kompilieren. (jemanden vorschlagen, dass Python nicht neu kompilieren.)Wenn wir halten die regex-Objekt mit (A) der regex-Objekt wird immer noch in _cache und geleert erhalten irgendwie. Aber unsere code halten eine Referenz auf es und das regex-Objekt nicht aus dem Speicher freigegeben. Diejenigen, Python müssen nicht erneut kompilieren.
Den 2 Sekunden Unterschiede in George ' s test compiledInLoop vs kompiliert ist vor allem die Zeit, die erforderlich, um das erstellen der Schlüssel und Suche die _cache. Es bedeutet nicht, dass das kompilieren der regex.
George ' s reallycompile test zeigen, was passiert, wenn es wirklich wieder tun, das kompilieren jedes mal: es wird 100x langsamer (reduzierte er die Schleife von der 1.000.000-10.000).
Hier sind nur die Fälle, dass (A + B) ist besser als (C):
Fall, dass (C) ist gut genug:
Nur eine Zusammenfassung, hier sind die A, B, C:
Vielen Dank für das Lesen.
InformationsquelleAutor der Antwort John Pang
Meist gibt es kaum einen Unterschied, ob Sie re.kompilieren oder nicht. Intern, alle Funktionen sind implementiert, ein compile-Schritt:
Zusätzlich, re.compile() umgeht den extra Umweg und Logik:
Neben der kleinen Geschwindigkeit nutzen von re.kompilierendie Menschen auch wie die Lesbarkeit, das kommt von der Benennung potenziell komplexen Muster, Spezifikationen und trennen Sie Sie von der business-Logik, wo es angewendet werden:
Hinweis, eine andere befragte fälschlicherweise angenommen, dass pyc gespeicherten Dateien kompiliert Muster direkt; aber in Wirklichkeit sind Sie wieder aufgebaut, jedes mal, wenn die PYC ist geladen:
Den oben Demontage kommt von der PYC-Datei für eine
tmp.py
mit:InformationsquelleAutor der Antwort Raymond Hettinger
Allgemein finde ich es einfacher zu benutzen Flaggen (zumindest einfacher zu merken, wie), wie
re.I
beim kompilieren Muster, als auf die use-flags inline.vs
InformationsquelleAutor der Antwort ptone
Anhand der vorgegebenen Beispiele:
Den match - Methode im obigen Beispiel ist nicht dieselbe wie die, die unten verwendet:
re.compile() gibt eine regular expression-Objektswas bedeutet, dass
h
ist ein regex-Objekt.Den regex-Objekt hat seine eigene match Methode mit dem optionalen pos und endpos Parameter:
regex.match(string[, pos[, endpos]])
pos
endpos
Des regex-Objekts Suchefindallund finditer Methoden unterstützen auch diese Parameter.
re.match(pattern, string, flags=0)
nicht zu unterstützen, wie Sie sehen können,noch hat seine Suche, findall, und finditer Kollegen.
Einen match-Objekt hat Attribute, ergänzen diese Parameter:
übereinstimmen.pos
übereinstimmen.endpos
Einen regex-Objekt hat zwei einzigartige, möglicherweise nützlich, attributes:
regex.Gruppen
regex.groupindex
Schließlich match-Objekt hat dieses Attribut:
übereinstimmen.re
InformationsquelleAutor der Antwort Honest Abe
Es ist ein Zusatz Vorteil der Verwendung von re.compile(), in form von hinzufügen von Kommentaren zu meinem regex-Muster mit re.AUSFÜHRLICHE
Obwohl dies keinen Einfluss auf die Geschwindigkeit der Ausführung von code, wie ich es so machen, wie es ist ein Teil meines kommentieren Gewohnheit. Ich Total nicht mögen, Zeit zu verbringen versuchte sich zu erinnern,, die Logik, ging hinter meinem code 2 Monaten auf der ganzen Linie, wenn ich will, um änderungen vorzunehmen.
InformationsquelleAutor der Antwort cyneo
Interessant auszuwerten, um nicht als effizienter für mich (Python 2.5.2 auf Win XP):
Ausführen der oben genannten code mal so wie es ist, und einmal mit den beiden
if
Linien, kommentierte der andere Weg herum, die zusammengestellt regex ist doppelt so schnellInformationsquelleAutor der Antwort Eli Bendersky
Lief ich diese testen, bevor Sie stolpernd auf die Diskussion hier. Allerdings haben dachte ich, ich zumindest poste meine Ergebnisse.
Ich Stahl und bastardized die beispielsweise in Jeff friedls "Mastering Regular Expressions". Dies ist auf einem macbook mit OS x 10.6 (2 GHz intel core 2 duo, 4GB ram). Python version ist die 2.6.1.
Ausführung 1 - mit re.kompilieren
Run 2 - Nicht mit re.kompilieren
InformationsquelleAutor der Antwort netricate
Performance-Unterschied abgesehen, mit re.kompilieren und mit der kompilierten regulären Ausdruck Objekt übereinstimmen (was auch immer reguläre Ausdruck verbundene Vorgänge) macht die Semantik klarer Python-Laufzeit.
Hatte ich einige schmerzhafte Erfahrungen Debuggen einige einfache code:
und später würde ich verwenden, zu vergleichen, in
wo
patternPhrases
soll eine variable, die den regulären Ausdruck stringx[columnIndex]
ist eine variable, die die Zeichenkette.Hatte ich Mühe, die
patternPhrases
nicht mit der zu erwartenden string!Aber wenn ich die re.kompilieren form:
dann in
Python würde haben sich beschwert, dass "Zeichenfolge nicht über das Attribut der match", als durch positionelle argument-mapping in
compare
x[columnIndex]
ist als regulärer Ausdruck verwendet!, wenn ich meinte eigentlichIn meinem Fall, mit re.kompilieren ist expliziter Zweck der reguläre Ausdruck, wenn der Wert ausgeblendet ist, Nackte Augen, so konnte ich weitere Hilfe von Python-run-time-Prüfung.
Also die moral von meinem Lektion ist, dass, wenn der reguläre Ausdruck ist nicht nur wörtlich string, dann sollte ich über die re.kompilieren zu lassen, Python, mir zu helfen, zu behaupten, meine Annahme.
InformationsquelleAutor der Antwort
Diese Antwort vielleicht spät, ist aber eine interessante finden. Mit kompilieren hat, kann wirklich sparen Sie Zeit, wenn Sie planen, über die Verwendung der regex mehrfach (dies ist auch erwähnt in der Dokumentation). Unten können Sie sehen, dass die Verwendung einer kompilierten regex am schnellsten, wenn Sie die match-Methode wird direkt aufgerufen. die übergabe eines regex kompiliert neu.match macht es sogar noch langsamer und die übergabe erneut.übereinstimmung mit dem Muster-string irgendwo in der Mitte.
InformationsquelleAutor der Antwort Akilesh
Neben der Leistung.
Mit
compile
hilft mir zu unterscheiden, die Konzepte1. Modul(re),
2. regex-Objekt
3. match-Objekt
Als ich angefangen zu lernen, regex
Als Ergänzung, ich machte eine umfassende cheatsheet von Modul
re
für Ihre Referenz.InformationsquelleAutor der Antwort JawSaw
Dies ist eine gute Frage. Sie sehen oft Menschen über die re.kompilieren, ohne Grund. Es vermindert die Lesbarkeit. Aber sicher, es gibt viele Male, wenn Sie vor-kompilieren der Ausdruck aufgerufen wird. Wie, wenn Sie es mal wiederholt in einer Schleife oder so.
Es ist wie alles über die Programmierung (alles, was im Leben eigentlich). Gelten gesunden Menschenverstand.
InformationsquelleAutor der Antwort PEZ
Ich respektiere wirklich alle oben genannten Antworten. Aus meiner Meinung nach
Ja! Sicher lohnt es sich, über die re.kompilieren kompilieren der regex, wieder und wieder, jedes mal.
Beispiel :
Mit in Findall
Mit in die Suche
InformationsquelleAutor der Antwort The Gr8 Adakron
(Monate später), es ist einfach zu fügen Sie Ihre eigenen cache rund um die re.match
oder irgendetwas anderes für diese Angelegenheit --
Einen wibni, wäre es nicht schön, wenn: cachehint( Größe= ), cacheinfo() -> die Größe, trifft, nclear ...
InformationsquelleAutor der Antwort denis
Stimmen auf die akzeptierte Antwort führt zu der Annahme, dass das, was @Triptychon sagt, ist wahr für alle Fälle. Dies ist nicht unbedingt wahr. Ein großer Unterschied ist, wenn Sie haben zu entscheiden, ob zu akzeptieren, die ein regex-string oder eine kompilierte regex-Objekts als parameter an eine Funktion:
Ist es immer besser, zu kompilieren, regexs in den Fall, Sie brauchen, um Sie wiederzuverwenden.
Hinweis: das Beispiel in der timeit oben simuliert die Erstellung einer kompilierten regex-Objekt, sobald beim import versus "on-the-fly", wenn erforderlich, für ein Spiel.
InformationsquelleAutor der Antwort lonetwin
Reguläre Ausdrücke kompiliert werden, bevor Sie verwendet werden, wenn mit Hilfe der zweiten version. Wenn Sie ausführen es viele Male ist es definitiv besser, es zuerst kompilieren. Wenn nicht kompilieren jedes mal, wenn Sie übereinstimmen, für eine off ist in Ordnung.
InformationsquelleAutor der Antwort Adam Peck
möchte ich motivieren, dass pre-compiling ist sowohl konzeptionell und 'literately' (wie in 'literate programming') vorteilhaft. haben Sie einen Blick auf dieses code-snippet:
in Ihrer Anwendung, Sie würde schreiben:
dies ist etwa so einfach, in Bezug auf Funktionalität, wie es bekommen kann. weil dieses Beispiel ist so kurz, ich zusammengefasst der Weg, um
_text_has_foobar_re_search
alle in einer Zeile. der Nachteil bei diesem code ist, dass es nimmt wenig Speicher für das, was der Lebensdauer derTYPO
library-Objekt ist; der Vorteil ist, dass wenn Sie einen Tee suchen, werden Sie Weg mit zwei Funktionsaufrufe und die zwei-Klassen-Wörterbuch lookups. wie viele regexes zwischengespeichert werden durchre
und der Aufwand, die Caches sind hier irrelevant.vergleichen Sie diese mit den üblichen Stil, unten:
In der Anwendung:
Ich gebe zu, dass mein Stil ist sehr ungewöhnlich für python, vielleicht sogar fraglich. im Beispiel ist aber, dass genau entspricht, wie python wird meist verwendet, um ein einzelnes Spiel, müssen wir instanziieren ein Objekt, können Sie drei Beispiel-Wörterbuch lookups, und führen Sie drei Funktionsaufrufe; darüber hinaus könnten wir bekommen, in
re
caching-Probleme bei der Verwendung von mehr als 100 regexes. auch mit dem regulären Ausdruck steht, verdeckt innerhalb der Methode Körper, die meisten der Zeit, ist nicht so eine gute Idee.sei es gesagt, daß jede Teilmenge der Maßnahmen---gezielte, alias import-Anweisungen; alias-Methoden, wo zutreffend; Reduktion der Funktionsaufrufe und die Objekt-dictionary lookups---kann dazu beitragen, rechnerische und begriffliche Komplexität.
InformationsquelleAutor der Antwort flow
Mein Verständnis ist, dass diese beiden Beispiele sind effektiv entspricht. Der einzige Unterschied ist, dass in der ersten, können Sie die Wiederverwendung der kompilierte reguläre Ausdruck anderswo, ohne dass es neu kompiliert werden.
Hier ist eine Referenz für Sie: http://diveintopython3.ep.io/refactoring.html
InformationsquelleAutor der Antwort Matthew Maravillas