当前位置: 首页 > 面试题库 >

为什么未编译,反复使用的正则表达式在Python 3中如此慢?

齐甫
2023-03-14
问题内容

当回答这个问题时,我以为我知道Python如何缓存正则表达式。

但是后来我想我会比较两种情况进行测试:

  1. 一个简单正则表达式的单个编译,然后是该已编译正则表达式的10个应用程序
  2. 一个未编译的正则表达式的10个应用程序(我曾预期性能会稍差一些,因为该正则表达式必须先编译一次,然后缓存,然后在缓存中查找9次)。

但是,结果令人震惊(在Python 3.3中):

>>> import timeit
>>> timeit.timeit(setup="import re", 
... stmt='r=re.compile(r"\w+")\nfor i in range(10):\n r.search("  jkdhf  ")')
18.547793477671938
>>> timeit.timeit(setup="import re", 
... stmt='for i in range(10):\n re.search(r"\w+","  jkdhf  ")')
106.47892003890324

慢了5.7倍!在Python 2.7中,仍然增加了2.5倍,这也比我预期的要多。

正则表达式的缓存在Python
2和3之间是否发生了变化?该文档似乎没有建议。


问题答案:

代码 更改。

在Python
2.7中,缓存是一个简单的字典。如果其中_MAXCACHE存储了多个项目,则在存储新项目之前将清除整个缓存。缓存查找只需要构建一个简单的键并测试字典,请参见2.7的实现_compile()

在Python 3.x中,缓存已由@functools.lru_cache(maxsize=500, typed=True)decorator代替。这个装饰做

更多的工作,包括螺纹锁固,调整缓存LRU队列和维护缓存统计信息(通过访问re._compile.cache_info())。参见3.3.0执行_compile()functools.lru_cache()

其他人也注意到了同样的减速,并在Python
Bugtracker中提交了问题16389。我希望3.4会再次更快。要么lru_cache改进实现,要么re模块将再次移至自定义缓存。

更新:对于版本4b4dddd670d0(hg)/
0f606a6(git),缓存更改已恢复为3.1中的简单版本。Python版本3.2.4和3.3.1包括该修订版。

从那时起,在Python
3.7中,模式缓存已根据常规更新为自定义FIFO缓存实现dict(依赖于插入顺序,并且与LRU不同,它不考虑撤出时最近使用缓存中的项目的最新情况)。



 类似资料:
  • 问题内容: 我正在研究道格·海尔曼(Doug Hellman)的“示例Python标准库”,并发现了这一点: “ 1.3.2编译表达式re包含用于将正则表达式作为文本字符串使用的模块级函数,但是编译程序经常使用的表达式更为有效。” 对于这种情况,我无法理解他的解释。他说“模块级功能维护编译后的表达式的缓存”,并且由于“缓存的大小”受到限制,因此“直接使用编译后的表达式可以避免缓存查找开销。” 如果

  • 编译正则表达式 正则表达式被编译成 RegexObject 实例,可以为不同的操作提供方法,如模式匹配搜索或字符串替换。 #python >>> import re >>> p = re.compile('ab*') >>> print p <_sre.SRE_Pattern object at 0xb76e1a70> re.compile() 也接受可选的标志参数,常用来实现不同的特殊功能和语

  • 正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。 Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。 re 模块使 Python 语言拥有全部的正则表达式功能。 compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。 re 模块也提供了与这些方法功能完全一致的

  • 问题内容: 我正在做一个小的javascript方法,该方法会接收到一个点列表,并且我必须阅读这些点才能在Google地图中创建多边形。 我在表格上收到这些要点: (lat,long),(lat,long),(lat,long) 因此,我完成了以下正则表达式: 我已经使用RegexPal和收到的确切数据进行了测试: 并且它可以正常工作,所以为什么当我在JavaScript中添加此代码后,结果中会收

  • 还有,谁能给我解释一下 , , , ?

  • 我的Java程序中有这个正则表达式 我也想在正则表达式中包含[和]。我也尝试使用转义字符,但没有成功。如何将这些字符添加到我的正则表达式中? 使用此示例 我试过\[和[,它不工作 上一次运行上述代码时,输出<code>Test:false