首先想到的是使用生成器表达式将循环推到 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
似乎并不比你原来的方法快。动态构建正则表达式也不是很快。但是,如果您可以设法预先构建一个正则表达式并多次使用它,这可能会带来更好的性能。您还可以调整此基准来测试其他一些选项:)