Quel est le type de l'expression régulière compilée en python?
En particulier, je veux évaluer
isinstance(re.compile(''), ???)
pour être vrai, à des fins d'introspection.
Une solution que j’avais était la suivante: ayez une constante REGEX_TYPE = type(re.compile(''))
globale, mais elle ne semble pas très élégante.
EDIT: La raison pour laquelle je veux faire cela est parce que j'ai une liste de chaînes et des objets regex compilés. Je veux "faire correspondre" une chaîne à la liste, par
et le code que je suis venu avec était:
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
Lorsque le type de quelque chose n'est pas bien spécifié, l'utilisation de la variable type
pour découvrir la réponse au moment de l'exécution n'a rien de mal:
>>> import re
>>> retype = type(re.compile('hello, world'))
>>> isinstance(re.compile('goodbye'), retype)
True
>>> isinstance(12, retype)
False
>>>
La découverte du type au moment de l'exécution vous évite d'avoir à accéder aux attributs privés et aux modifications futures du type de retour. Il n'y a rien d'inélégant à utiliser type
ici, bien qu'il puisse y avoir quelque chose d'inélégant à vouloir connaître le type du tout.
Python 3.5 a introduit le module typing
. Il contient typing.re.Pattern
, un _TypeAlias
.
À partir de Python 3.6, vous pouvez simplement faire:
from typing.re import Pattern
my_re = re.compile('foo')
assert isinstance(my_re, Pattern)
Dans la version 3.5, il y avait un bug vous obligeant à faire ceci:
assert issubclass(type(my_re), Pattern)
Ce qui n’est pas garanti pour fonctionner selon la documentation et la suite de tests.
Il est possible de comparer une expression régulière compilée avec 're._pattern_type'
import re
pattern = r'aa'
compiled_re = re.compile(pattern)
print isinstance(compiled_re, re._pattern_type)
>>True
Donne True, au moins dans la version 2.7
Avertissement: Ceci n'est pas conçu comme une réponse directe à vos besoins spécifiques, mais plutôt comme une solution pouvant être utile comme approche alternative
Vous pouvez rester fidèle aux idéaux de la frappe au canard et utiliser hasattr
pour déterminer si l'objet possède certaines propriétés que vous souhaitez utiliser. Par exemple, vous pourriez faire quelque chose comme:
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
Mieux vaut prévenir que guérir. Ne créez pas une liste aussi hétérogène en premier lieu. Avoir un set de chaînes autorisées et une liste d'objets regex compilés. Cela devrait améliorer l'apparence de votre code de contrôle et le rendre plus rapide:
if input in allowed_strings:
ignored = False
else:
for allowed in allowed_regexed_objects:
if allowed.match(input):
ignored = False
break
Si vous ne pouvez pas éviter la création d'une telle liste, voyez si vous avez la possibilité de l'examiner une fois et de créer les deux objets de remplacement.
Pour illustrer le polymorphisme, une autre solution consiste à créer des classes wrapper qui implémentent une méthode commune.
class Stringish (str):
def matches (self, input):
return self == input
class Regexish (re):
def matches (self, input):
return self.match(input)
Désormais, votre code peut parcourir une liste d'objets alloweds
contenant des instances instanciant l'une ou l'autre de ces deux classes de manière totalement transparente:
for allowed in alloweds:
if allowed.matches(input):
ignored = False
break
Notez également comment une partie de la duplication de code disparaît (bien que votre code d'origine ait pu être refactoré pour résoudre ce problème séparément).
Un exemple de ce type de code est fourni dans BeautifulSoup: http://www.crummy.com/software/BeautifulSoup et utilise la technique du 'hasattr' encapsulez également votre recherche de chaîne dans une expression rationnelle en procédant comme suit: regexp = re.compile (re.escape (your_string)) Par conséquent, vous ne disposez que d'une liste d'expressions régulières.
Ceci est un autre pas la réponse à la question, mais cela résout le problème réponse. À moins que your_string ne contienne des caractères spéciaux d'expression régulière,
if re.match(your_string,target_string):
a le même effet que
if your_string == target_string:
Revenez donc un pas en arrière et utilisez des modèles d’expression régulière non compilés dans votre liste de personnes autorisées. Cela est sans doute plus lent que l’utilisation d’expressions régulières compilées, mais cela ne fonctionnera qu’en cas de résultat inattendu, et ce uniquement si vous autorisez les utilisateurs à fournir les éléments autorisés
En 3.7, vous pouvez utiliser re.Pattern
:
import re
rr = re.compile("pattern")
isinstance(rr, re.Pattern)
>> True