web-dev-qa-db-fra.com

Type d'objet regex compilé en python

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

  • pour chaque chaîne de la liste, essayez de vérifier l’égalité des chaînes.
  • pour chaque expression régulière dans la liste, essayez de vérifier si la chaîne correspond au modèle donné.

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
58
Jeeyoung Kim

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.

30

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.

30
flying sheep

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

19
alemol

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
15
bgw

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.

10
John Machin

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).

7
tripleee

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.

3
Scout

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

0
griswolf

En 3.7, vous pouvez utiliser re.Pattern:

import re
rr = re.compile("pattern")
isinstance(rr, re.Pattern)
>> True
0
DominiCane