Вот худший случай:
Все казалось идеальным. Потратив пару часов, я понял, что файл jquery, который добавлен в правильную позицию, на самом деле был файлом с пустым содержимым!
Не думаю, что это тривиально. Я не хочу, чтобы в моем коде появлялось лишнее условие, если я часто пишу такой код.
Это немного странно, но вы можете сделать это с помощью итератора:
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», это кажется естественным расширением.
Я не думаю, что использование с
является решением в данном случае. Вы' 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
Как вы можете видеть в комментариях ниже, этот метод не является ни областью действия, ни потокобезопасностью. Вы могли бы использовать это только в том случае, если бы были полностью уверены, что ваше приложение не станет многопоточным в будущем и что любые функции, вызываемые из области, в которой вы это используете, будут также использовать тот же метод .
Если вы делаете много этого в одном месте, вот альтернативный ответ:
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 в более широком контексте, чем этот; это вызовет те же проблемы, что и решение Бликста.