Was ist der Typ des kompilierten regulären Ausdrucks in Python?
Insbesondere möchte ich bewerten
isinstance(re.compile(''), ???)
um wahr zu sein, zu Zwecken der Selbstbeobachtung.
Eine Lösung, die ich hatte, war, eine globale Konstante zu haben REGEX_TYPE = type(re.compile(''))
, aber sie scheint nicht sehr elegant zu sein.
BEARBEITEN: Der Grund, warum ich dies tun möchte, ist, dass ich eine Liste von Zeichenfolgen und kompilierten Regex-Objekten habe. Ich möchte eine Zeichenfolge mit der Liste "abgleichen"
- Versuchen Sie für jede Zeichenfolge in der Liste, die Zeichenfolgengleichheit zu überprüfen.
- Überprüfen Sie für jeden regulären Ausdruck in der Liste, ob die Zeichenfolge mit dem angegebenen Muster übereinstimmt.
und der Code, den ich mir ausgedacht habe, war:
for allowed in alloweds:
if isinstance(allowed, basestring) and allowed == input:
ignored = False
break
elif isinstance(allowed, REGEX_TYPE) and allowed.match(input):
ignored = False
break
re._pattern_type
das, was aus einem bestimmten Grund wahrscheinlich mit einem Unterstrich beginnt.duck taping
:)Antworten:
Wenn der Typ von etwas nicht genau angegeben ist, ist es nichts Falsches,
type
wenn Sie das integrierte Programm verwenden, um die Antwort zur Laufzeit zu ermitteln:>>> import re >>> retype = type(re.compile('hello, world')) >>> isinstance(re.compile('goodbye'), retype) True >>> isinstance(12, retype) False >>>
Das Erkennen des Typs zur Laufzeit schützt Sie vor dem Zugriff auf private Attribute und vor zukünftigen Änderungen des Rückgabetyps. Es ist nichts Unelegantes an der Verwendung
type
hier, obwohl es etwas Unelegantes sein kann, den Typ überhaupt kennen zu wollen.quelle
Python 3.5 hat das
typing
Modul eingeführt. Darin enthalten isttyping.Pattern
, a_TypeAlias
.Ab Python 3.6 können Sie einfach Folgendes tun:
from typing import Pattern my_re = re.compile('foo') assert isinstance(my_re, Pattern)
In Version 3.5 gab es einen Fehler , bei dem Sie Folgendes tun mussten:
assert issubclass(type(my_re), Pattern)
Was laut Dokumentation und Testsuite nicht garantiert funktioniert.
quelle
from typing import Pattern
um darauf zuzugreifenPattern
.typing.re
wurde in 3.6 entfernt, denke ichEs ist möglich, einen kompilierten regulären Ausdruck mit 're._pattern_type' zu vergleichen.
import re pattern = r'aa' compiled_re = re.compile(pattern) print isinstance(compiled_re, re._pattern_type) >>True
Gibt True, zumindest in Version 2.7
quelle
Haftungsausschluss: Dies ist keine direkte Antwort auf Ihre spezifischen Anforderungen, sondern eine Alternative, die als alternativer Ansatz nützlich sein kann
Sie können sich an die Ideale der Ententypisierung halten und
hasattr
bestimmen, ob das Objekt bestimmte Eigenschaften aufweist, die Sie verwenden möchten. Zum Beispiel könnten Sie etwas tun wie:if hasattr(possibly_a_re_object, "match"): # Treat it like it's an re object possibly_a_re_object.match(thing_to_match_against) else: # alternative handler
quelle
Vorbeugung ist besser als Heilung. Erstellen Sie überhaupt keine so heterogene Liste. Verfügen Sie über eine Reihe zulässiger Zeichenfolgen und eine Liste kompilierter Regex-Objekte. Dadurch sollte Ihr Prüfcode besser aussehen und schneller ausgeführt werden:
if input in allowed_strings: ignored = False else: for allowed in allowed_regexed_objects: if allowed.match(input): ignored = False break
Wenn Sie die Erstellung einer solchen Liste nicht vermeiden können, prüfen Sie, ob Sie die Möglichkeit haben, sie einmal zu untersuchen und die beiden Ersatzobjekte zu erstellen.
quelle
ignored = not any(allowed.match(input) for allowed in allowed_regexed_objects))
.Zur Veranschaulichung des Polymorphismus besteht eine alternative Lösung darin, Wrapper-Klassen zu erstellen, die eine gemeinsame Methode implementieren.
class Stringish (str): def matches (self, input): return self == input class Regexish (re): def matches (self, input): return self.match(input)
Jetzt kann Ihr Code eine Liste
alloweds
mit Objekten durchlaufen, die eine dieser beiden Klassen vollständig transparent instanziieren:for allowed in alloweds: if allowed.matches(input): ignored = False break
Beachten Sie auch, wie einige Codeduplikationen verschwinden (obwohl Ihr ursprünglicher Code möglicherweise überarbeitet wurde, um dies separat zu beheben).
quelle
str
umbasestring
da in Py2, beideunicode
undstr
erben vonbasestring
.re
ist ein klassenloses Modul, das nicht einfach mit einem Klassenvererbungsmodell erweitert werden kann.re
; Die Hauptsache ist, eine gleichnamige Methode mit zwei verschiedenen Implementierungen zu haben.Regexish
, erben vonobject
, dann rufen Sie einfachre
an__init__
, um einre
Objekt nach Komposition zu erstellen (da Sie, wie Sie sagen, nur implementieren müssenmatches
odersearch
Zu Ihrer Information, ein Beispiel für einen solchen Code befindet sich in BeautifulSoup: http://www.crummy.com/software/BeautifulSoup und verwendet die 'hasattr'-Technik. Im Sinne des "alternativen Ansatzes" können Sie Ihre Zeichenfolgensuche auch in einem regulären Ausdruck kapseln, indem Sie Folgendes tun: regexp = re.compile (re.escape (your_string)), daher nur eine Liste regulärer Ausdrücke.
quelle
In 3.7 können Sie verwenden
re.Pattern
:import re rr = re.compile("pattern") isinstance(rr, re.Pattern) >> True
quelle
Dies ist eine andere nicht die Antwort auf die Frage, aber es löst die Problemantwort . Sofern your_string keine Sonderzeichen für reguläre Ausdrücke enthält,
if re.match(your_string,target_string):
hat den gleichen Effekt wie
if your_string == target_string:
Gehen Sie also einen Schritt zurück und verwenden Sie nicht kompilierte Muster für reguläre Ausdrücke in Ihrer Liste der zulässigen. Dies ist zweifellos langsamer als die Verwendung kompilierter regulärer Ausdrücke, funktioniert jedoch nur gelegentlich mit unerwarteten Ergebnissen, und zwar nur dann, wenn Sie Benutzern erlauben, die zulässigen Elemente anzugeben
quelle
>>> import re >>> regex = re.compile('foo') >>> regex <_sre.SRE_Pattern object at 0x10035d960>
Nun - _sre ist eine C-Erweiterung, die den Mustervergleich durchführt. Sie können in der _sre C-Quelle nachsehen.
Warum kümmert es dich?
Oder du versuchst so etwas (aus welchem Grund auch immer - es ist mir egal):
>>> regex1 = re.compile('bar') >>> regex2 = re.compile('foo') >>> type(regex1) == type(regex2) True
quelle
_sre
Modul hat hier kein solches Attribut.from _sre import SRE_Pattern
dies nicht funktioniert. Die Abstimmungen sind wahrscheinlich 1. aufgrund Ihrer Einstellung: "Es ist mir egal" - was? Und 2. weil du die Frage nicht wirklich beantwortet hast.