如果在函数内部编译正则表达式,并且该函数被多次调用,那么Python每次都会重新编译正则表达式,还是Python缓存编译的正则表达式(假设正则表达式没有改变)?
例如:
def contains_text_of_interest(line):
r = re.compile(r"foo\dbar\d")
return r.match(line)
def parse_file(fname):
for line in open(fname):
if contains_text_of_interest(line):
# Do something interesting
答案 0 :(得分:12)
实际上,如果你看一下re模块中的代码,re.compile函数就像所有其他函数一样使用缓存,所以一遍又一遍地编译相同的regex是非常便宜的(字典查找) 。换句话说,将代码编写为最易理解或可维护或表达的代码,并且不必担心编译正则表达式的开销。
答案 1 :(得分:6)
如果你想避免每次调用re.compile()的开销,你可以这样做:
def contains_text_of_interest(line, r = re.compile(r"foo\dbar\d")):
return r.match(line)
答案 2 :(得分:2)
为什么不直接将re.compile放在函数外(在模块或类级别),给它一个明确的名称并使用它?这种正则表达式是一种常数,你可以用同样的方式对待它。
MATCH_FOO_BAR = re.compile(r"foo\dbar\d")
def contains_text_of_interest(line):
return MATCH_FOO_BAR.match(line)
答案 3 :(得分:2)
Dingo的解决方案是一个很好的解决方案[编辑:Ned Batchelder的解释更好],但这是另一个我觉得很整洁的解决方案:使用闭包!如果这听起来像是一个“大字”,请不要担心。这个概念很简单:
def make_matching_function():
matcher = re.compile(r"foo\dbar\d")
def f(line):
return matcher.match(line)
return f
contains_text_of_interest = make_matching_function()
make_matching_function
只被调用一次,因此正则表达式只编译一次。分配给f
的函数contains_text_of_interest
知道已编译的正则表达式matcher
,因为它位于周围范围内,并且即使您使用{{1}也会始终知道它在其他地方(那是闭包:用它来获取周围范围的代码)。
肯定不是解决这个问题的最恐怖的解决方案。但是,如果时间合适,这是一个很好的习惯,因为时间恰到好处:)
答案 4 :(得分:0)
它做了“错误”的事情,这是关于这个主题的更长的话题。