Альтернатива 'соответствию = re.match (); если соответствие: …' идиома?

Вот худший случай:

Все казалось идеальным. Потратив пару часов, я понял, что файл jquery, который добавлен в правильную позицию, на самом деле был файлом с пустым содержимым!

33
задан Cœur 27 October 2018 в 09:26
поделиться

3 ответа

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

Это немного странно, но вы можете сделать это с помощью итератора:

import re

def rematch(pattern, inp):
    matcher = re.compile(pattern)
    matches = matcher.match(inp)
    if matches:
        yield matches

if __name__ == '__main__':
    for m in rematch("(\d+)g", "123g"):
        print(m.group(1))

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

Кажется странным, что диспетчер контекста может ' t приводит к тому, что его управляемая функция полностью пропускается; хотя это явно не один из вариантов использования слова «with», это кажется естественным расширением.

12
ответ дан 27 November 2019 в 19:34
поделиться

Я не думаю, что использование с является решением в данном случае. Вы' d должен вызывать исключение в части BLOCK (которая указывается пользователем) и иметь метод __ exit __ , возвращающий True , чтобы «проглотить» исключение. Так что это никогда не будет хорошо выглядеть.

Я бы предложил использовать синтаксис, аналогичный синтаксису Perl. Создайте свой собственный расширенный модуль re (я назову его rex ) и задайте ему переменные в пространстве имен модуля:

if rex.match('(\d+)g', '123g'):
    print rex._1

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

Создайте свой собственный расширенный модуль re (я назову его rex ) и задайте ему переменные в пространстве имен модуля:

if rex.match('(\d+)g', '123g'):
    print rex._1

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

Создайте свой собственный расширенный модуль re (я назову его rex ) и задайте ему переменные в пространстве имен модуля:

if rex.match('(\d+)g', '123g'):
    print rex._1

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

0
ответ дан 27 November 2019 в 19:34
поделиться

Если вы делаете много этого в одном месте, вот альтернативный ответ:

import re
class Matcher(object):
    def __init__(self):
        self.matches = None
    def set(self, matches):
        self.matches = matches
    def __getattr__(self, name):
        return getattr(self.matches, name)

class re2(object):
    def __init__(self, expr):
        self.re = re.compile(expr)

    def match(self, matcher, s):
        matches = self.re.match(s)
        matcher.set(matches)
        return matches

pattern = re2("(\d+)g")
m = Matcher()
if pattern.match(m, "123g"):
    print(m.group(1))
if not pattern.match(m, "x123g"):
    print "no match"

Вы можете скомпилировать регулярное выражение один раз с той же безопасностью потока, что и re, создать один объект Matcher многократного использования для всей функции, а затем вы можете используйте его очень кратко. Это также имеет то преимущество, что вы можете отменить его очевидным способом - чтобы сделать это с помощью итератора, вам нужно будет передать флаг, чтобы он инвертировал результат.

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

0
ответ дан 27 November 2019 в 19:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: