Первое, что приходит на ум, — это перенести цикл на сторону C с помощью выражения генератора:
def matches_pattern(s, patterns):
return any(p.match(s) for p in patterns)
Возможно, вам даже не нужна отдельная функция для этого.
Еще одна вещь, которую вы должны попробовать, — создать одно составное регулярное выражение с использованием оператора чередования |
, чтобы у движка была возможность оптимизировать его для вас. Вы также можете создать регулярное выражение динамически из списка шаблонов строк, если это необходимо:
def matches_pattern(s, patterns):
return re.match('|'.join('(?:%s)' % p for p in patterns), s)
Конечно, вам нужно, чтобы ваши регулярные выражения были в строковой форме, чтобы это работало. Просто профилируйте оба из них и проверьте, какой из них быстрее :)
Вы также можете ознакомиться с общим советом по отладке регулярных выражений в Python. Это также может помочь найти возможности для оптимизации.
ОБНОВЛЕНИЕ: мне стало любопытно, и я написал небольшой тест:
import timeit
setup = """
import re
patterns = [".*abc", "123.*", "ab.*", "foo.*bar", "11010.*", "1[^o]*"]*10
strings = ["asdabc", "123awd2", "abasdae23", "fooasdabar", "111", "11010100101", "xxxx", "eeeeee", "dddddddddddddd", "ffffff"]*10
compiled_patterns = list(map(re.compile, patterns))
def matches_pattern(str, patterns):
for pattern in patterns:
if pattern.match(str):
return True
return False
def test0():
for s in strings:
matches_pattern(s, compiled_patterns)
def test1():
for s in strings:
any(p.match(s) for p in compiled_patterns)
def test2():
for s in strings:
re.match('|'.join('(?:%s)' % p for p in patterns), s)
def test3():
r = re.compile('|'.join('(?:%s)' % p for p in patterns))
for s in strings:
r.match(s)
"""
import sys
print(timeit.timeit("test0()", setup=setup, number=1000))
print(timeit.timeit("test1()", setup=setup, number=1000))
print(timeit.timeit("test2()", setup=setup, number=1000))
print(timeit.timeit("test3()", setup=setup, number=1000))
Вывод на моей машине:
1.4120500087738037
1.662621021270752
4.729579925537109
0.1489570140838623
Так что any
не кажется быстрее, чем ваш первоначальный подход. Динамическое создание регулярного выражения также не очень быстрое. Но если вам удастся создать регулярное выражение заранее и использовать его несколько раз, это может привести к повышению производительности. Вы также можете адаптировать этот тест для тестирования некоторых других вариантов :)
14.05.2012
'|'.join(patterns)
небезопасно. Regex — сложный язык. Вы хотите сначала обернуть каждый термин в(?:...)
, чтобы быть в безопасности. 15.05.2012any
. 15.05.2012