Типа скомпилированный объект регулярных выражений в Python


каков тип скомпилированного регулярного выражения в python?

в частности, я хочу оценить

isinstance(re.compile(''), ???)

чтобы быть правдой, для целей интроспекции.

одно решение у меня было, есть некоторые глобальные константы REGEX_TYPE = type(re.compile('')), но это не кажется очень элегантным.

EDIT: почему я хочу сделать это потому, что у меня есть список строк, и скомпилированных объектов regex. Я хочу "сопоставить" строку со списком, на

  • для каждой строки в списке, попробуйте для проверки равенства строк.
  • для каждого регулярного выражения в списке попробуйте проверить, соответствует ли строка заданному шаблону.

и код, который я придумал:

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
9 53

9 ответов:

когда тип чего-то не очень хорошо указан, нет ничего плохого в использовании type строение, чтобы найти ответ во время выполнения:

>>> import re
>>> retype = type(re.compile('hello, world'))
>>> isinstance(re.compile('goodbye'), retype)
True
>>> isinstance(12, retype)
False
>>> 

обнаружение типа во время выполнения защищает вас от необходимости доступа к частным атрибутам и от будущих изменений возвращаемого типа. Нет ничего неэлегантного в использовании type здесь, хотя может быть что-то неэлегантное о желании знать тип вообще.

Python 3.5 представил typing модуль. В него входит typing.re.Pattern, a _TypeAlias.

начиная с Python 3.6, вы можете просто сделать:

from typing.re import Pattern

my_re = re.compile('foo')
assert isinstance(my_re, Pattern)

в 3.5, там был ошибка требуя от вас сделать это:

assert issubclass(type(my_re), Pattern)

который не гарантирует работу в соответствии с документацией и набором тестов.

можно сравнить скомпилированное регулярное выражение с ' re._pattern_type'

import re
pattern = r'aa'
compiled_re = re.compile(pattern)
print isinstance(compiled_re, re._pattern_type)

>>True

дает True, по крайней мере в версии 2.7

отказ от ответственности: Это не предназначено как прямой ответ для ваших конкретных потребностей, а скорее что-то, что может быть полезно в качестве альтернативного подхода


Вы можете сохранить с идеалами утка набрав, и использовать hasattr определить, если объект имеет определенные свойства, которые вы хотите использовать. Например, вы могли бы сделать что-то вроде:

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

профилактика лучше, чем лечение. Не создавайте такой разнородный список в первую очередь. Есть set разрешенных строк и списка скомпилированных объектов регулярных выражений. Это должно сделать ваш код проверки выглядеть лучше и работать быстрее:

if input in allowed_strings:
    ignored = False
else:
    for allowed in allowed_regexed_objects:
        if allowed.match(input):
            ignored = False
            break

Если вы не можете избежать создания такого списка, посмотрите, есть ли у вас возможность изучить его один раз и построить два объекта замены.

в качестве иллюстрации полиморфизма альтернативным решением является создание классов-оболочек, которые реализуют общий метод.

class Stringish (str):
    def matches (self, input):
        return self == input

class Regexish (re):
    def matches (self, input):
        return self.match(input)

Теперь ваш код может перебирать список alloweds содержащие объекты, создающие экземпляры любого из этих двух классов полностью прозрачно:

for allowed in alloweds:
    if allowed.matches(input):
        ignored = False
        break

заметьте также, как некоторое дублирование кода уходит (хотя ваш исходный код может быть переработан, чтобы исправить это отдельно).

FYI пример такого кода находится в BeautifulSoup:http://www.crummy.com/software/BeautifulSoup и использует технику 'hasattr'. В духе "альтернативного подхода" вы также можете инкапсулировать свой поиск строк в регулярное выражение, выполнив это: регулярное выражение = ре.компиляции(ре.escape(your_string)) поэтому есть список только регулярных выражений.

Это еще один не ответ на вопрос, но это решает проблему ответ. Если your_string не содержит специальных символов регулярного выражения,

if re.match(your_string,target_string):

аналогично

if your_string == target_string:

поэтому отступите на один шаг и используйте несжатые шаблоны регулярных выражений в своем списке разрешенных. Это, несомненно, медленнее, чем использование скомпилированных регулярных выражений, но он будет работать только с случайным неожиданным результатом, и это только если вы разрешить пользователям поставлять разрешенные элементы

>>> import re
>>> regex = re.compile('foo')
>>> regex
<_sre.SRE_Pattern object at 0x10035d960>

Well-_sre-это расширение C, выполняющее сопоставление шаблонов...вы можете посмотреть в источнике _sre C.

почему тебя это волнует?

или вы попробуете что - то вроде этого (по какой-то причине-мне все равно):

>>> regex1 = re.compile('bar')
>>> regex2 = re.compile('foo')
>>> type(regex1) == type(regex2)
True