在多次调用的函数内编译正则表达式

时间:2010-08-06 20:00:42

标签: python regex

如果在函数内部编译正则表达式,并且该函数被多次调用,那么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

5 个答案:

答案 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)

它做了“错误”的事情,这是关于这个主题的更长的话题。

I'm using Python regexes in a criminally inefficient manner