我偶然发现了以下代码:
import re
regex_compiled = re.compile('\d{2}-\d{3,5}')
res = re.search(regex_compiled, '12-9876')
我的印象是re.search
尝试编译已经编译的第一个参数,因此它应该在重复尝试编译它之前应该调用错误或regex_compiled.__repr__()
或regex_compiled.__str__()
!
只是为了确保我将其与regex_compiled.search(...
进行比较:
>>> from timeit import timeit
>>> timeit("import re; regex_compiled = re.compile('\d{2}-\d{3,5}'); res = re.search(regex_compiled, '12-9876')")
1.3797054840251803
>>> timeit("import re; regex_compiled = re.compile('\d{2}-\d{3,5}'); res = regex_compiled.search('12-9876')")
0.7649686150252819
>>>
鉴于调试re.search
(在CPython v.2和v.3中)显示编译的模式被重用,我感到非常困惑。我希望有人可以帮助阐明这一点。
执行环境:Ubuntu 16.04,64b
答案 0 :(得分:2)
re._compile
首先检查参数是否被缓存,然后是否已编译。因此,当您将已编译的模式传递给re.whatever
时,它会浪费一些时间来计算并查找实际上永远不会匹配的缓存键。重复模式和OrderedDict
查找是繁重的操作,似乎可以解释您观察到的差异。
此行为的一个可能原因是_compile
针对字符串模式进行了优化,这是其主要用例,旨在尽快返回缓存命中。
以下是一些时间安排:
from time import time
import re
import sys
print(sys.version)
pat = '\d{2}-\d{3,5}'
loops = 1000000
re.purge()
t = time()
for _ in range(loops):
re._compile(pat, 0)
print('compile string ', time() - t)
re.purge()
rc = re._compile(pat, 0)
t = time()
for _ in range(loops):
re._compile(rc, 0)
print('compile compiled', time() - t)
结果:
$ python3 test.py
3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 20160609]
compile string 0.5387749671936035
compile compiled 0.7378756999969482
$ python2 test.py
2.7.12 (default, Nov 20 2017, 18:23:56) [GCC 5.4.0 20160609]
('compile string ', 0.5074479579925537)
('compile compiled', 1.3561439514160156)