Рубрики
Без рубрики

Python Regex Compile.

Метод Re.comPile (Pattern) Возвращает регулярное объект выражения из шаблона, который обеспечивает базовые методы Regex, такие как Pattern.Search (Strattion), Pattern.match (Strattion) и Pattern.findall (String). Явный двухэтапный подход (1) компиляция и (2) поиска шаблона более эффективен, чем вызов, скажем, поиск (шаблон, строка) сразу, если вы совпадете в одном и том же шаблоне несколько раз, потому что он избегает … Python Regeex Compile Прочитайте больше “

Автор оригинала: Chris.

Метод Re.compile (Pattern) Возвращает регулярное объект выражения из шаблон Это обеспечивает базовые методы Regex, такие как Pattern.Search (строка) , Pattern.match (строка) и Pattern.findall (строка) Отказ Явный двухэтапный подход (1) компиляция и (2) поиск шаблона более эффективно, чем вызов, скажем, Поиск (шаблон, строка) Сразу, если вы сопоставьте один и тот же шаблон несколько раз, потому что это позволяет избежать избыточных компиляций одного и того же шаблона.

Почему регулярные выражения выжили Семь десятилетий технологических нарушений ? Потому что кодеры, которые понять регулярные выражения иметь огромное преимущество при работе с Текстовые данные Отказ Они могут написать в Одна линия кода Что делает других десятков!

Эта статья все о Re.compile (Pattern) Метод Python Re Библиотека Отказ Прежде чем мы погрузиться в re.compile () Давайте получим обзор четырех связанных методов, которые вы должны понимать:

  • findall (шаблон, строка) Метод возвращает Список строковых матчей Отказ Читайте больше в Наше руководство в блоге Отказ
  • Поиск (шаблон, строка) Метод возвращает Матч объект первого матча Отказ Читайте больше в Наше руководство в блоге Отказ
  • Матч (шаблон, строка) Метод возвращает Матч объект Если регеекс совпадает на Начало строки Отказ Читайте больше в Наше руководство в блоге Отказ
  • FullMatch (шаблон, строка) Метод возвращает Матч объект Если Regex соответствует целая строка Отказ Читайте больше в Наше руководство в блоге Отказ

Связанная статья: Python Regex SuperPower – Ultimate Guide

Оснащен этим быстрым обзором наиболее критически важных методов Regex, давайте ответим на следующий вопрос:

Как работает re.compile () в Python?

То Re.compile (Pattern) Метод возвращает объект регулярного выражения. Затем вы используете объект, чтобы вызвать важные методы Regex, такие как Поиск (строка) , Матч (строка) , fullmatch (строка) , и findall (строка) .

Короче говоря: вы компилируете шаблон сначала. Вы ищете шаблон в строке второй.

Этот двухэтапный подход более эффективен, чем звон, скажем, Поиск (шаблон, строка) однажды. То есть Если вы позвоните Поиск () Метод несколько раз на тот же шаблон Отказ Почему? Потому что вы можете повторно использовать скомпилированный шаблон несколько раз.

Вот пример:

import re

# These two lines ...
regex = re.compile('Py...n')
match = regex.search('Python is great')

# ... are equivalent to ...
match = re.search('Py...n', 'Python is great')

В обоих случаях переменная матча содержит следующий объект совпадения:

Но в первом случае мы можем найти шаблон не только в строке «Питон отличный «Но и в других строках – без каких-либо избыточных работ компиляции шаблона снова и снова.

Спецификация :

re.compile(pattern, flags=0)

Метод имеет до двух аргументов.

  • шаблон : Регулярное выражение выражения, которое вы хотите сопоставить.
  • Флаги (Необязательный аргумент): более продвинутый модификатор, который позволяет настроить поведение функции. Хотите знать Как использовать эти флаги? Проверьте эту подробную статью на блог Finxter.

Мы подробно рассмотрим эти аргументы позже.

Возвращаемое значение:

re.compile (узоры, флаги) Метод возвращает объект регулярного выражения. Вы можете спросить (и правильно):

Какой объект регулярного выражения?

Python внутренне создает Объект регулярного выражения (Из Pattern класс) для подготовки процесса соответствия шаблона. Вы можете вызвать следующие методы на объекте Regex:

Pattern.Search (строка [, POS [, ENDPOS]]) Ищется Regex в любом месте строки и возвращает объект совпадения или нет. Вы можете определить начальные и конечные позиции поиска.
Pattern.match (строка [, pos [, endpos]])) Ищет регулярное выражение в начале строки и возвращает объект матча или нет. Вы можете определить начальные и конечные позиции поиска.
Pattern.fullmatch (строка [, POS [, ENDPOS]]) Соответствует Regex со всей строкой и возвращает объект Match или None. Вы можете определить начальные и конечные позиции поиска.
Pattern.split (строка) Делит строку в список подстроки. Regex – разделитель. Вы можете определить максимальное количество расщеплений.
Pattern.findall (строка [, POS [, ENDPOS]])) Выполнивает Regex в любом месте строки и возвращает список подходящих подстрок. Вы можете определить начальные и конечные позиции поиска.
Pattern.finditer (строка [, POS [, ENDPOS]])) Возвращает итератор, который переходит на все спички Regex в строке (возвращает один объект совпадения за другим). Вы можете определить начальные и конечные позиции поиска.
Package.sub (rep, string,) Возвращает новую строку, заменив первые вхождения вхождения Regex в строке (слева направо) с помощью замены String Rep.
Pattern.subn (rep, string,) Возвращает новую строку, заменив первые вхождения вхождения Regex в строке (слева направо) с помощью замены String Rep. Однако он возвращает кортеж с замененной строкой в качестве первого и количества успешных замен в качестве второго значения кортежа.

Если вы знакомы с наиболее основными методами Regex, вы поймете, что все они появляются в этой таблице. Но есть одно различие: вам не нужно определять шаблон как аргумент. Например, метод Regex Re.Search (шаблон, строка) Внутри скомпилируйте объект Regex P а потом звоните P.Search (строка) Отказ

Вы можете увидеть этот факт в официальной реализации Re.Search (шаблон, строка) Метод :

def search(pattern, string, flags=0):
    """Scan through string looking for a match to the pattern, returning
    a Match object, or None if no match was found."""
    return _compile(pattern, flags).search(string)

(Источник: репозиторий GitHub повторной упаковки)

Re.Search (Pattern, String ) Метод является простой обертком для составления шаблона сначала и вызывая P.Search (строка) Функция на скомпилированном объекте Regex P Отказ

Вы хотите освоить сверхдержаву Regeex? Проверьте мою новую книгу Самый умный способ изучать регулярные выражения в Python С инновационным 3-ступенчатым подходом для активного обучения: (1) Изучение книги главы, (2) Решите головоломки кода и (3) Смотреть воспроизведение главы видео.

Стоит ли использовать Python’s Re.compile ()?

Нет, в подавляющем большинстве случаев, это не стоит дополнительной линии.

Рассмотрим следующий пример:

import re

# These two lines ...
regex = re.compile('Py...n')
match = regex.search('Python is great')

# ... are equivalent to ...
match = re.search('Py...n', 'Python is great')

Не поймите меня неправильно. Составление рисунка один раз и используя его много раз на протяжении всего вашего кода (например, в A Loop ) поставляется с большой производительностью. В некоторых случаях анекдота, составление шаблона сначала привести к 10x до 50x Speedup по сравнению с составлением его снова и снова.

Но причина, по которой она не стоит дополнительной линии, это то, что библиотека Python Re Bistance с внутренним кэшем. Во время этого письма кэш имеет ограничение до 512 скомпилированных объектов REGEX. Так что в течение первых 512 раз вы можете быть уверены при звонке Re.Search (шаблон, строка) что кэш содержит скомпилированный шаблон уже.

Вот соответствующий кодовый фрагмент из Репозиторий Re’s Github :

# --------------------------------------------------------------------
# internals

_cache = {}  # ordered!

_MAXCACHE = 512
def _compile(pattern, flags):
    # internal: compile pattern
    if isinstance(flags, RegexFlag):
        flags = flags.value
    try:
        return _cache[type(pattern), pattern, flags]
    except KeyError:
        pass
    if isinstance(pattern, Pattern):
        if flags:
            raise ValueError(
                "cannot process flags argument with a compiled pattern")
        return pattern
    if not sre_compile.isstring(pattern):
        raise TypeError("first argument must be string or compiled pattern")
    p = sre_compile.compile(pattern, flags)
    if not (flags & DEBUG):
        if len(_cache) >= _MAXCACHE:
            # Drop the oldest item
            try:
                del _cache[next(iter(_cache))]
            except (StopIteration, RuntimeError, KeyError):
                pass
        _cache[type(pattern), pattern, flags] = p
    return p

Можете ли вы найти места, где кэш инициализируется и используется?

В большинстве случаев вам не нужно компилировать шаблон в некоторых случаях. Они следуют непосредственно из предыдущей реализации:

  • У тебя больше, чем MaxCache Узоры в вашем коде.
  • У тебя больше, чем MaxCache Разные Шаблоны между двумя то же самое экземпляры схема. Только в этом случае вы увидите «пропустить кэш», где кэш уже прократил, казалось бы, скорейшие экземпляры шаблонов, чтобы освободить место для более новых.
  • Вы используете шаблон несколько раз. Потому что, если вы этого не сделаете, не имеет смысла использовать редкую память, чтобы сохранить их в вашей памяти.
  • (Даже тогда это может быть полезно только в том случае, если узоры относительно сложны. В противном случае вы не увидите много преимуществ производительности на практике.)

Чтобы обобщить, сначала компиляцию шаблона и хранение скомпилированного рисунка в переменной для более позднего использования часто бывает ничего, кроме «преждевременной оптимизации», – одна из смертных грехов начинающих и промежуточных программиров.

Что делает Re.compile () действительно?

Это не кажется много, не делает это? Моя интуиция заключалась в том, что реальная работа находится в нахождении шаблона в тексте, который происходит после компиляции. И, конечно же, сопоставляя шаблон это тяжелая часть. Но разумная компиляция много помогает приготовить шаблон, который должен быть эффективно сопутствуется с помощью двигателя Regex, которая в противном случае была бы выполнена двигателем Regex.

Regex’s Компилировать () Метод делает много вещей, таких как:

  • Объедините два последующих символа в Regex, если они вместе указывают на особый символ, такой как определенные греческие символы.
  • Приготовьте регельс, чтобы игнорировать прописные и строчные.
  • Проверьте на определенные (меньшие) шаблоны в Regex.
  • Анализируйте соответствующие группы в Regex, заключенном в скобки.

Вот реализация Компилировать () Метод – это выглядит более сложно, чем ожидалось, нет?

def _compile(code, pattern, flags):
    # internal: compile a (sub)pattern
    emit = code.append
    _len = len
    LITERAL_CODES = _LITERAL_CODES
    REPEATING_CODES = _REPEATING_CODES
    SUCCESS_CODES = _SUCCESS_CODES
    ASSERT_CODES = _ASSERT_CODES
    iscased = None
    tolower = None
    fixes = None
    if flags & SRE_FLAG_IGNORECASE and not flags & SRE_FLAG_LOCALE:
        if flags & SRE_FLAG_UNICODE:
            iscased = _sre.unicode_iscased
            tolower = _sre.unicode_tolower
            fixes = _ignorecase_fixes
        else:
            iscased = _sre.ascii_iscased
            tolower = _sre.ascii_tolower
    for op, av in pattern:
        if op in LITERAL_CODES:
            if not flags & SRE_FLAG_IGNORECASE:
                emit(op)
                emit(av)
            elif flags & SRE_FLAG_LOCALE:
                emit(OP_LOCALE_IGNORE[op])
                emit(av)
            elif not iscased(av):
                emit(op)
                emit(av)
            else:
                lo = tolower(av)
                if not fixes:  # ascii
                    emit(OP_IGNORE[op])
                    emit(lo)
                elif lo not in fixes:
                    emit(OP_UNICODE_IGNORE[op])
                    emit(lo)
                else:
                    emit(IN_UNI_IGNORE)
                    skip = _len(code); emit(0)
                    if op is NOT_LITERAL:
                        emit(NEGATE)
                    for k in (lo,) + fixes[lo]:
                        emit(LITERAL)
                        emit(k)
                    emit(FAILURE)
                    code[skip] = _len(code) - skip
        elif op is IN:
            charset, hascased = _optimize_charset(av, iscased, tolower, fixes)
            if flags & SRE_FLAG_IGNORECASE and flags & SRE_FLAG_LOCALE:
                emit(IN_LOC_IGNORE)
            elif not hascased:
                emit(IN)
            elif not fixes:  # ascii
                emit(IN_IGNORE)
            else:
                emit(IN_UNI_IGNORE)
            skip = _len(code); emit(0)
            _compile_charset(charset, flags, code)
            code[skip] = _len(code) - skip
        elif op is ANY:
            if flags & SRE_FLAG_DOTALL:
                emit(ANY_ALL)
            else:
                emit(ANY)
        elif op in REPEATING_CODES:
            if flags & SRE_FLAG_TEMPLATE:
                raise error("internal: unsupported template operator %r" % (op,))
            if _simple(av[2]):
                if op is MAX_REPEAT:
                    emit(REPEAT_ONE)
                else:
                    emit(MIN_REPEAT_ONE)
                skip = _len(code); emit(0)
                emit(av[0])
                emit(av[1])
                _compile(code, av[2], flags)
                emit(SUCCESS)
                code[skip] = _len(code) - skip
            else:
                emit(REPEAT)
                skip = _len(code); emit(0)
                emit(av[0])
                emit(av[1])
                _compile(code, av[2], flags)
                code[skip] = _len(code) - skip
                if op is MAX_REPEAT:
                    emit(MAX_UNTIL)
                else:
                    emit(MIN_UNTIL)
        elif op is SUBPATTERN:
            group, add_flags, del_flags, p = av
            if group:
                emit(MARK)
                emit((group-1)*2)
            # _compile_info(code, p, _combine_flags(flags, add_flags, del_flags))
            _compile(code, p, _combine_flags(flags, add_flags, del_flags))
            if group:
                emit(MARK)
                emit((group-1)*2+1)
        elif op in SUCCESS_CODES:
            emit(op)
        elif op in ASSERT_CODES:
            emit(op)
            skip = _len(code); emit(0)
            if av[0] >= 0:
                emit(0) # look ahead
            else:
                lo, hi = av[1].getwidth()
                if lo != hi:
                    raise error("look-behind requires fixed-width pattern")
                emit(lo) # look behind
            _compile(code, av[1], flags)
            emit(SUCCESS)
            code[skip] = _len(code) - skip
        elif op is CALL:
            emit(op)
            skip = _len(code); emit(0)
            _compile(code, av, flags)
            emit(SUCCESS)
            code[skip] = _len(code) - skip
        elif op is AT:
            emit(op)
            if flags & SRE_FLAG_MULTILINE:
                av = AT_MULTILINE.get(av, av)
            if flags & SRE_FLAG_LOCALE:
                av = AT_LOCALE.get(av, av)
            elif flags & SRE_FLAG_UNICODE:
                av = AT_UNICODE.get(av, av)
            emit(av)
        elif op is BRANCH:
            emit(op)
            tail = []
            tailappend = tail.append
            for av in av[1]:
                skip = _len(code); emit(0)
                # _compile_info(code, av, flags)
                _compile(code, av, flags)
                emit(JUMP)
                tailappend(_len(code)); emit(0)
                code[skip] = _len(code) - skip
            emit(FAILURE) # end of branch
            for tail in tail:
                code[tail] = _len(code) - tail
        elif op is CATEGORY:
            emit(op)
            if flags & SRE_FLAG_LOCALE:
                av = CH_LOCALE[av]
            elif flags & SRE_FLAG_UNICODE:
                av = CH_UNICODE[av]
            emit(av)
        elif op is GROUPREF:
            if not flags & SRE_FLAG_IGNORECASE:
                emit(op)
            elif flags & SRE_FLAG_LOCALE:
                emit(GROUPREF_LOC_IGNORE)
            elif not fixes:  # ascii
                emit(GROUPREF_IGNORE)
            else:
                emit(GROUPREF_UNI_IGNORE)
            emit(av-1)
        elif op is GROUPREF_EXISTS:
            emit(op)
            emit(av[0]-1)
            skipyes = _len(code); emit(0)
            _compile(code, av[1], flags)
            if av[2]:
                emit(JUMP)
                skipno = _len(code); emit(0)
                code[skipyes] = _len(code) - skipyes + 1
                _compile(code, av[2], flags)
                code[skipno] = _len(code) - skipno
            else:
                code[skipyes] = _len(code) - skipyes + 1
        else:
            raise error("internal: unsupported operand type %r" % (op,))

Не нужно все понимать в этом коде. Просто отметьте, что вся эта работа должна быть сделана двигателем Regex в «Соответствующем времени выполнения», если вы сначала не скомпилируйте шаблон. Если мы сможем сделать это только один раз, это, безусловно, с низким виселом для оптимизации производительности – особенно для длительного регулярного выражения.

Как использовать дополнительный аргумент флага?

Как вы видели в спецификации, Компилировать () Метод поставляется с необязательным третьим Флаги Аргумент:

re.compile(pattern, flags=0)

Какова цель аргумента флагов?

Флаги позволяют управлять регулярным механизмом выражения. Поскольку регулярные выражения настолько мощны, они являются полезным способом включения и отключения определенных функций (например, следует ли игнорировать капитализацию при сопоставлении вашего Regex).

Синтаксис Значение
Re.ascii. Если вы не используете этот флаг, специальные символы Regex Python \ W, \ W, \ b, \ b, \ d, \ d, \ s и \ s будут соответствовать символам Unicode. Если вы используете этот флаг, эти специальные символы будут соответствовать только символам ASCII – как указано имя.
реаяна Так же, как Re.Ascii
Re.debug. Если вы используете этот флаг, Python распечатает некоторую полезную информацию в оболочку, которая помогает отладить ваше регулярное выражение.
Re.ignorecase. Если вы используете этот флаг, двигатель Regex будет выполнять совпадение в случае сопоставления. Поэтому, если вы ищете [A-Z], он также будет соответствовать [A-Z].
Re.i. Так же, как Re.ignoRecase
Re.Locale Не используйте этот флаг – когда-либо. Он обесценился – идея состояла в том, чтобы выполнить сопоставление нечувствительности к регистру в зависимости от вашей текущей местности. Но это не надежно.
решающее значение Так же, как Re.Locale
Re.multiline. Этот флаг включает в следующую функцию: начало строки Regex ‘^’ совпадает в начале каждой строки (а не только в начале строки). То же самое относится и к концу строки Regex ‘$’, который сейчас соответствует также в конце каждой строки в многострочной строке.
решающее значение Так же, как Re.multiline.
re.dotall. Без использования этого флага точечное регулярное выражение. ‘ Соответствует всем персонажам, кроме нового символа «n». Переключите этот флаг, чтобы действительно сопоставить все символы, включая новенький символ.
республика Так же, как Re.dotall.
Re.verbose. Чтобы улучшить читаемость сложных регулярных выражений, вы можете позволить комментариям и (многострочному) форматированию самого Regeex. Это возможно с этим флагом: все пробелы и строки, которые начинаются с символа «#», игнорируются в Regex.
re.x. Так же, как Re.verbose

Вот как бы вы использовали его в практическом примере:

import re

text = 'Python is great (python really is)'

regex = re.compile('Py...n', flags=re.IGNORECASE)

matches = regex.findall(text)
print(matches)
# ['Python', 'python']

Хотя ваше регулярное выражение «Питон» является заглавным, мы игнорируем капитализацию, используя флаг Re.ignoRecase Отказ

Куда пойти отсюда?

Вы узнали о Re.compile (Pattern) Метод, который готовит шаблон регулярного выражения – и возвращает объект REGEX, который вы можете использовать несколько раз в вашем коде.

Обучение Python сложно. Но если вы обманываете, это не так сильно, как должно быть:

Скачать 8 бесплатных читов Python сейчас!

Инженеры Google, Facebook и Amazon являются регулярными мастерами. Если вы хотите стать одним, а также проверить нашу новую книгу: Самый умный способ изучить Python Regex (Amazon Kindle/Print, открывается на новой вкладке) Отказ

Работая в качестве исследователя в распределенных системах, доктор Кристиан Майер нашел свою любовь к учению студентов компьютерных наук.

Чтобы помочь студентам достичь более высоких уровней успеха Python, он основал сайт программирования образования Finxter.com Отказ Он автор популярной книги программирования Python One-listers (Nostarch 2020), Coauthor of Кофе-брейк Python Серия самооставленных книг, энтузиаста компьютерных наук, Фрилансера и владелец одного из лучших 10 крупнейших Питон блоги по всему миру.

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