python - 在 re.search 中重用已编译的正则表达式

标签 python regex python-2.7 python-3.5

我偶然发现了以下代码:

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

最佳答案

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)

关于python - 在 re.search 中重用已编译的正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48883647/

相关文章:

python - OAuth API Google 云端硬盘 Python

python - 设置Flask+uWSGI+nginx的最佳实践

python - Python代码返回: Syntaxerror non-keyword after keyword arg

python - 在 Python 3 中使用 RSA,需要对消息进行签名(不对消息进行哈希处理)

java - java中的UNICODE正则表达式

python - 如何使用 python 2.7 替换字符串中的当前单词?

python - 仅运行 python 脚本的 Eclipse 插件

c# - 从解析的字符串构建多级数组数组/锯齿状数组

c++ - 从字符串 C++ 中删除元音

Python:计数直到列表中的元素是元组