【问题标题】:How to compile multiple multiple regexes in one go? Is it more efficient? - python如何一次编译多个多个正则表达式?是不是更有效率? - Python
【发布时间】:2015-12-28 16:03:56
【问题描述】:

假设我有这样的代码:

import re
docid_re = re.compile(r'<DOCID>([^>]+)</DOCID>')
doctype_re = re.compile(r'<DOCTYPE SOURCE="[^"]+">([^>]+)</DOCTYPE>')
datetime_re = re.compile(r'<DATETIME>([^>]+)</DATETIME>')

我也可以这样做:

>>> import re
>>> docid_re = r'<DOCID>([^>]+)</DOCID>'
>>> doctype_re = r'<DOCTYPE SOURCE="[^"]+">([^>]+)</DOCTYPE>'
>>> datetime_re = r'<DATETIME>([^>]+)</DATETIME>'
>>> docid_re, doctype_re, datetime_re = map(re.compile, [docid_re, doctype_re, datetime_re])
>>> docid_re
<_sre.SRE_Pattern object at 0x7f0314eee438>

但是当我使用map() 时,速度或内存有什么真正的提升吗?

【问题讨论】:

  • 你在用正则表达式解析xml吗?
  • 确实是这样。
  • 你试过测量吗?

标签: python regex dictionary compilation


【解决方案1】:

不要听任何人的 - 只是衡量它!您可以使用timeit 模块。但请记住,“premature optimization is the root of all evil”(c) Donald Knuth。

顺便说一句,回答你的问题“不,这根本没有帮助”。

【讨论】:

  • 实际上,timeit 模块在这种情况下会欺骗你。 re.compile caches the compiled forms of the regexes it compiles,因此您可能会将性能改进视为相对于总成本的实质性好处,而实际上,在实际代码中,已编译的正则表达式不会在缓存中,与编译成本相比,节省是微不足道的首先。您需要在每个循环上显式地 re.purge() 缓存(当然,这会增加不同类型的混淆开销)。
  • @alvas,自动 - ShadowRanger 已经在官方文档中添加了 link。您可以在Note 部分阅读它。
  • 显式编译和隐式编译的主要区别在于显式编译意味着你得到一个可以直接使用的regex对象;如果对象是本地的或在类实例上,查找比导入到全局命名空间中的re 更便宜(感谢LEGB 搜索)。当你使用模块级函数时,它仍然需要在缓存中查找模式以找到regex,如果你使用了一堆其他regexregex 可能已经过期等等。显式@987654336 @ 避免了这种情况。
  • 坦率地说,我最喜欢编译正则表达式的一点是,它可以让您使用多个 regex 方法和一个参数,这意味着它可以很容易地与函数方法一起使用,例如 map、@987654339 @(和multiprocessing.Pool上的类似方法); mapfilter 通常比等效的列表解析 (Py2) 或生成器表达式 (Py3) 慢,但对于较大的迭代,当映射函数/过滤谓词在 C 中实现时(regex 方法大多是)、mapfilter 更快,因为它们避免了查找成本并将所有执行推送到 C 层(当然仅在 CPython 中)。
  • @Jimilian:郑重声明,我同意过早优化是万恶之源。我很奇怪的唯一原因是,这是我以前使用timeit(通过ipython's %timeit 魔术)来调查这类东西的性能的案例之一,所以我有足够的经验说“是的,它可以更快,但不,加速永远不会有意义”。
【解决方案2】:

如果您要编译 很多 正则表达式,map 可能有助于避免查找 re 所涉及的查找成本,然后在每次调用时获取其 compile 属性;使用map,您查找一次map 和一次re.compile,然后它会被一遍又一遍地使用而无需进一步查找。当然,当您需要构建一个 list 来使用它时,您会消耗掉这些节省。实际上,您需要大量的正则表达式才能达到map 值得您花时间的地步;对于三个人来说,这可能是一种损失。

即使它确实有帮助,也只是最小的微优化。如果它使代码更清晰,我会这样做,性能充其量是第三个关注点。在某些情况下(例如,将一个巨大的整数文本文件解析为ints)map 可能是一个巨大的胜利,因为启动它的开销被减少的查找和 Python 字节码执行开销所补偿。但这不是其中一种情况,而且这些情况非常罕见,以至于在 99.99% 的情况下都不值得担心。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-31
    • 1970-01-01
    • 2015-07-03
    • 1970-01-01
    • 2017-08-04
    相关资源
    最近更新 更多