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
我有很多运行编译的regex 1000次的经验,也没有注意到任何可感知的差异。显然,这是一个轶事,当然也不是反对编译的有力论据,但我发现两者之间的差别可以忽略不计。
编辑: 在快速浏览了实际的Python2.5库代码之后,我发现无论何时使用正则表达式(包括对
re.match()
的调用),Python都会在内部编译和缓存正则表达式,因此只有当正则表达式被编译时,您才会真正地改变,而且根本不应该节省太多时间—只需要检查缓存所需的时间(对内部dict
类型的键查找)。来自模块re.py(注释是我的):
我仍然经常预编译正则表达式,但只是将它们绑定到一个好的、可重用的名称,而不是为了获得任何预期的性能提升。
前进方向:
因此,如果您要经常使用相同的regex,那么做
re.compile
(特别是对于更复杂的regex)可能是值得的。反对过早优化的标准论据适用,但如果您怀疑regexp可能会成为性能瓶颈,那么使用
re.compile
并不会真正失去清晰性/直截了当性。更新:
在Python3.6(我怀疑上述计时是使用Python2.x)和2018硬件(MacBook Pro)下,我现在得到以下计时:
我还添加了一个case(注意最后两次运行之间的引号差异),它表明
re.match(x, ...)
实际上[大致]相当于re.compile(x).match(...)
,即编译表示的后台缓存似乎不会发生。对我来说,
re.compile
的最大好处是能够将regex的定义与其使用分离开来。即使是一个简单的表达式,如
0|[1-9][0-9]*
(基数10中不带前导零的整数),也可能非常复杂,以至于您不必重新键入它,检查是否有任何输入错误,稍后在开始调试时必须重新检查是否有输入错误。另外,使用变量名(如num或numúb10)比使用0|[1-9][0-9]*
更好。当然,存储字符串并将其传递给re.match是可能的;但是,这会使的可读性降低:
与编译相比:
虽然很接近,但第二行的最后一行在重复使用时感觉更自然、更简单。
相关问题 更多 >
编程相关推荐