Тип скомпилированного объекта регулярного выражения в python
Каков тип скомпилированного регулярного выражения в python?
В частности, я хочу оценить
isinstance(re.compile(''), ???)
чтобы быть правдой, для целей самоанализа.
Одно из решений, которое у меня было, имело некоторую глобальную константу REGEX_TYPE = type(re.compile(''))
, но это не кажется очень изящным.
EDIT: Причина, по которой я хочу сделать это, состоит в том, что у меня есть список строк и скомпилированные объекты регулярных выражений. Я хочу "сопоставить" строку со списком,
- для каждой строки в списке, попробуйте проверить равенство строки.
- для каждого регулярного выражения в списке, попробуйте проверить, соответствует ли строка данному шаблону.
и код, который я придумал, был:
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
Ответы
Ответ 1
Если тип чего-то не уточнен, нет ничего плохого в использовании встроенного встроенного type
для обнаружения ответа во время выполнения:
>>> import re
>>> retype = type(re.compile('hello, world'))
>>> isinstance(re.compile('goodbye'), retype)
True
>>> isinstance(12, retype)
False
>>>
Обнаружение типа во время выполнения защищает вас от необходимости доступа к приватным атрибутам и к будущим изменениям типа возврата. Здесь нет ничего необычного в использовании type
, хотя может быть что-то нелепое о желании узнать тип вообще.
Ответ 2
В Python 3.5 появился модуль typing
. В него включены typing.Pattern
и _TypeAlias
.
Начиная с Python 3.6, вы можете просто сделать:
from typing import Pattern
my_re = re.compile('foo')
assert isinstance(my_re, Pattern)
В 3.5 раньше была ошибка, требующая от вас сделать это:
assert issubclass(type(my_re), Pattern)
Который не гарантирует работу в соответствии с документацией и набором тестов.
Ответ 3
Можно сравнить скомпилированное регулярное выражение с 're._pattern_type'
import re
pattern = r'aa'
compiled_re = re.compile(pattern)
print isinstance(compiled_re, re._pattern_type)
>>True
Дает True, по крайней мере, в версии 2.7
Ответ 4
Отказ от ответственности: Это не предназначено как прямой ответ для ваших конкретных потребностей, а скорее что-то, что может быть полезно в качестве альтернативного подхода
Вы можете сохранить идеалы утиного ввода текста и использовать hasattr
, чтобы определить, есть ли у объекта определенные свойства, которые вы хотите использовать. Например, вы можете сделать что-то вроде:
if hasattr(possibly_a_re_object, "match"): # Treat it like it an re object
possibly_a_re_object.match(thing_to_match_against)
else:
# alternative handler
Ответ 5
Профилактика лучше, чем лечение. Не создавайте такой гетерогенный список в первую очередь. У вас есть set допустимых строк и список скомпилированных объектов регулярных выражений. Это должно сделать ваш код проверки лучше выглядеть и работать быстрее:
if input in allowed_strings:
ignored = False
else:
for allowed in allowed_regexed_objects:
if allowed.match(input):
ignored = False
break
Если вы не можете избежать создания такого списка, посмотрите, есть ли у вас возможность изучить его один раз и создать два объекта замены.
Ответ 6
В качестве иллюстрации полиморфизма альтернативным решением является создание классов-оболочек, которые реализуют общий метод.
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
Обратите внимание также, как некоторые дубликаты кода уходят (хотя исходный код мог быть реорганизован для исправления отдельно).
Ответ 7
FYI пример такого кода находится в BeautifulSoup: http://www.crummy.com/software/BeautifulSoup и использует технику 'hasattr'.
В духе "альтернативного подхода" вы также можете инкапсулировать свой поиск строк в регулярном выражении, выполнив следующее: regexp = re.compile(re.escape(your_string))
поэтому имеет список только регулярных выражений.
Ответ 8
Это еще один не ответ на вопрос, но он решает проблему ответа. Если ваша строка не содержит специальных символов регулярного выражения,
if re.match(your_string,target_string):
имеет тот же эффект, что и
if your_string == target_string:
Так что отступите на один шаг и используйте нескомпилированные шаблоны регулярных выражений в своем списке разрешенных. Это, несомненно, медленнее, чем использование скомпилированных регулярных выражений, но будет работать только с непредвиденным непредвиденным результатом, и только в том случае, если вы позволите пользователям предоставлять разрешенные элементы
Ответ 9
В 3.7 вы можете использовать re.Pattern
:
import re
rr = re.compile("pattern")
isinstance(rr, re.Pattern)
>> True
Ответ 10
>>> import re
>>> regex = re.compile('foo')
>>> regex
<_sre.SRE_Pattern object at 0x10035d960>
Хорошо - _sre - расширение C, выполняющее сопоставление шаблонов... вы можете посмотреть в источнике _sre C.
Почему вас это волнует?
Или вы попробуете что-то вроде этого (по какой-то причине - мне все равно):
>>> regex1 = re.compile('bar')
>>> regex2 = re.compile('foo')
>>> type(regex1) == type(regex2)
True