首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Python的re.compile值得吗?

使用Python的re.compile值得吗?
EN

Stack Overflow用户
提问于 2009-01-16 21:31:58
回答 27查看 359.8K关注 0票数 565

在Python中使用编译正则表达式有什么好处吗?

代码语言:javascript
运行
复制
h = re.compile('hello')
h.match('hello world')

vs

代码语言:javascript
运行
复制
re.match('hello', 'hello world')
EN

回答 27

Stack Overflow用户

回答已采纳

发布于 2009-01-16 21:42:58

我有过运行编译正则表达式数千次与动态编译相比的丰富经验,并且没有注意到任何可察觉的差异。显然,这只是一些轶事,当然也不是反对编译的一个很好的理由,但我发现两者的区别可以忽略不计。

编辑:快速浏览一下实际的Python2.5库代码后,我发现Python会在内部编译并缓存任何时候使用的正则表达式(包括对re.match()的调用),所以您实际上只是在编译正则表达式时进行了更改,而不应该节省太多时间--只节省了检查缓存(在内部dict类型上查找键)所需的时间。

来自模块re.py (注释是我的):

代码语言:javascript
运行
复制
def match(pattern, string, flags=0):
    return _compile(pattern, flags).match(string)

def _compile(*key):

    # Does cache check at top of function
    cachekey = (type(key[0]),) + key
    p = _cache.get(cachekey)
    if p is not None: return p

    # ...
    # Does actual compilation on cache miss
    # ...

    # Caches compiled regex
    if len(_cache) >= _MAXCACHE:
        _cache.clear()
    _cache[cachekey] = p
    return p

我仍然经常预编译正则表达式,但只是为了将它们绑定到一个好的、可重用的名称,而不是为了任何预期的性能提升。

票数 504
EN

Stack Overflow用户

发布于 2009-01-17 16:49:08

对我来说,re.compile最大的好处是能够将正则表达式的定义与使用分开。

即使是像0|[1-9][0-9]*这样的简单表达式(以10为基数的整数,没有前导零)也可能非常复杂,以至于您不需要重新键入它,检查是否有任何拼写错误,然后在开始调试时必须重新检查是否有拼写错误。此外,使用诸如num或num_b10之类的变量名比使用0|[1-9][0-9]*更好。

当然,也可以存储字符串并将其传递给re.match;但是,这样做的可读性较差:

代码语言:javascript
运行
复制
num = "..."
# then, much later:
m = re.match(num, input)

与编译相比:

代码语言:javascript
运行
复制
num = re.compile("...")
# then, much later:
m = num.match(input)

虽然它相当接近,但当重复使用时,第二行的最后一行感觉更自然和更简单。

票数 154
EN

Stack Overflow用户

发布于 2009-01-16 21:42:38

FWIW:

代码语言:javascript
运行
复制
$ python -m timeit -s "import re" "re.match('hello', 'hello world')"
100000 loops, best of 3: 3.82 usec per loop

$ python -m timeit -s "import re; h=re.compile('hello')" "h.match('hello world')"
1000000 loops, best of 3: 1.26 usec per loop

因此,如果您打算经常使用相同的正则表达式,那么使用re.compile可能是值得的(尤其是对于更复杂的正则表达式)。

反对过早优化的标准论点是适用的,但是如果您怀疑您的正则表达式可能会成为性能瓶颈,我认为使用re.compile并不会失去太多的清晰度/直截了当。

更新:

在Python3.6(我怀疑上面的计时是使用Python2.x完成的)和2018硬件(MacBook专业版)下,我现在得到以下计时:

代码语言:javascript
运行
复制
% python -m timeit -s "import re" "re.match('hello', 'hello world')"
1000000 loops, best of 3: 0.661 usec per loop

% python -m timeit -s "import re; h=re.compile('hello')" "h.match('hello world')"
1000000 loops, best of 3: 0.285 usec per loop

% python -m timeit -s "import re" "h=re.compile('hello'); h.match('hello world')"
1000000 loops, best of 3: 0.65 usec per loop

% python --version
Python 3.6.5 :: Anaconda, Inc.

我还添加了一个案例(请注意最后两次运行之间的引号差异),它表明re.match(x, ...)大致等同于re.compile(x).match(...),即似乎不会发生编译表示的幕后缓存。

票数 93
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/452104

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档