2010-08-06 74 views
13

如果在函數內部編譯正則表達式,並且該函數被多次調用,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 

回答

11

實際上,如果你看看re模塊中的代碼,re.compile函數就像所有其他函數一樣使用緩存這樣做,所以一遍又一遍地編譯相同的正則表達式非常便宜(字典查找)。換句話說,編寫代碼是最容易理解或可維護或表達的,並且不用擔心編譯正則表達式的開銷。

+0

你是對的,請參閱[re.py中的_compile函數](https://github.com/python/cpython/blob/master/Lib/re.py#L278) – pevik 2016-03-30 08:33:49

6

如果你想避免調用re.compile()每一次的開銷,你可以這樣做:

def contains_text_of_interest(line, r = re.compile(r"foo\dbar\d")): 
    return r.match(line) 
+4

+1我的話,我從來沒有想過我會看到Python的默認參數處理是*有用*。 – katrielalex 2010-08-06 21:23:56

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

這就是我迄今爲止所做的,但是這迫使我定義遠離它的使用的正則表達式比我想要的更遠。 – 2010-08-07 11:49:28

2

巴丁格的解決方案是一個很好的[編輯:斯內德爾德的解釋是更好],但這裏有另外一個我認爲是整齊的:使用閉!如果這聽起來像是一個「大詞彙」,不要擔心。這個概念很簡單:

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只調用一次,因此正則表達式編譯只有一次。編號爲contains_text_of_interest的函數f知道編譯後的正則表達式matcher,因爲它位於周圍的範圍內,並且始終知道它,即使在其他位置使用contains_text_of_interest(即,閉包:將周圍範圍與它一起使用的代碼) 。

當然,這不是對這個問題的最Pythonic解決方案。但是,這是一個很好的習慣用法,因爲時間是正確的:)