【发布时间】:2012-06-26 19:07:46
【问题描述】:
考虑一下这个 Python 代码:
import timeit
import re
def one():
any(s in mystring for s in ('foo', 'bar', 'hello'))
r = re.compile('(foo|bar|hello)')
def two():
r.search(mystring)
mystring="hello"*1000
print([timeit.timeit(k, number=10000) for k in (one, two)])
mystring="goodbye"*1000
print([timeit.timeit(k, number=10000) for k in (one, two)])
基本上,我正在对两种方法进行基准测试,以检查大字符串中是否存在多个子字符串之一。
我在这里得到的(Python 3.2.3)是这个输出:
[0.36678314208984375, 0.03450202941894531]
[0.6672089099884033, 3.7519450187683105]
在第一种情况下,正则表达式很容易击败 any 表达式 - 正则表达式会立即找到子字符串,而 any 必须检查整个字符串几次才能找到正确的子字符串。
但是在第二个例子中发生了什么?在子字符串不存在的情况下,正则表达式的速度非常慢!这让我感到惊讶,因为理论上正则表达式只需要遍历字符串一次,而 any 表达式必须遍历字符串 3 次。这里有什么问题?我的正则表达式有问题,还是在这种情况下 Python 正则表达式很慢?
【问题讨论】:
-
至少我可以确认时间,但我不知道为什么。 +1 用于奇怪和可复制粘贴的示例。
-
@JBernardo:你的意思是代替
one()中的元组?实际上,这没有什么区别。使用“foo|bar|hello”删除正则表达式中的组会使正则表达式花费 3.5 秒而不是 3.7 秒,但这仍然很慢。 -
如果您使用较长的字符串 (
'foo'*1000) 并排除简单的长度测试(将hello*1000更改为hello*200),您会发现 regexp 通常较慢,不仅仅是在第二个示例中. -
猜测,也许简单的字符串搜索已经过优化,因此它比较每个汇编指令的多个字节(使用一些 SIMD 指令?),而正则表达式不是。
-
@hamster:
'foo'*1000不是一个很有趣的案例,因为any表达式会立即短路。并且在这种情况下,正则表达式仍然更快,至少在这里 - 不过,正如您所期望的那样,它们大致相同。
标签: python regex python-3.x