在Python中使用编译正则表达式有什么好处吗?
h = re.compile('hello')
h.match('hello world')vs
re.match('hello', 'hello world')发布于 2009-01-16 21:42:58
我有过运行编译正则表达式数千次与动态编译相比的丰富经验,并且没有注意到任何可察觉的差异。显然,这只是一些轶事,当然也不是反对编译的一个很好的理由,但我发现两者的区别可以忽略不计。
编辑:快速浏览一下实际的Python2.5库代码后,我发现Python会在内部编译并缓存任何时候使用的正则表达式(包括对re.match()的调用),所以您实际上只是在编译正则表达式时进行了更改,而不应该节省太多时间--只节省了检查缓存(在内部dict类型上查找键)所需的时间。
来自模块re.py (注释是我的):
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我仍然经常预编译正则表达式,但只是为了将它们绑定到一个好的、可重用的名称,而不是为了任何预期的性能提升。
发布于 2009-01-17 16:49:08
对我来说,re.compile最大的好处是能够将正则表达式的定义与使用分开。
即使是像0|[1-9][0-9]*这样的简单表达式(以10为基数的整数,没有前导零)也可能非常复杂,以至于您不需要重新键入它,检查是否有任何拼写错误,然后在开始调试时必须重新检查是否有拼写错误。此外,使用诸如num或num_b10之类的变量名比使用0|[1-9][0-9]*更好。
当然,也可以存储字符串并将其传递给re.match;但是,这样做的可读性较差:
num = "..."
# then, much later:
m = re.match(num, input)与编译相比:
num = re.compile("...")
# then, much later:
m = num.match(input)虽然它相当接近,但当重复使用时,第二行的最后一行感觉更自然和更简单。
发布于 2009-01-16 21:42:38
FWIW:
$ 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专业版)下,我现在得到以下计时:
% 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(...),即似乎不会发生编译表示的幕后缓存。
https://stackoverflow.com/questions/452104
复制相似问题