2010-07-10 47 views
2

我正在使用re.sub回調來替換具有隨機值的子字符串,但我希望隨機值在不同的字符串中是相同的。由於re.sub回調不允許參數,我不知道如何做到這一點。如何將變量傳遞給re.sub回調?

下面是我在做什麼的簡化版本:

def evaluate(match): 
    mappings = {'A': 1, 'B': 2} 
    return str(eval(match.group(0)[2:-1], mappings)) 

# variables = {'A':[1,2,3,4,5], 'B':[1,2,3,4,5]}  
# mappings2 = {k:v[random.randint(0,len(v)-1)] for k, v in variables.items()} 
string_one: "#{A} + #{B}" 
string_two: "#{A+B}" 
newstring_one = sub(r'\#\{([^#]+)\}', evaluate, string_one) 
newstring_two = sub(r'\#\{([^#]+)\}', evaluate, string_two) 

現在,因爲它代表,該字符串將被正確評估:newstring_one爲「1 + 2」和newstring_two爲「3」。但我希望能夠隨機挑選這些值,並且仍然可以在兩個字符串中替換它們。這將涉及刪除「評估」中的「映射」行,並使用類似兩條註釋行的內容。但是,如果我不能在re.sub回調函數中將它作爲參數傳遞,那麼如何在評估兩個字符串時使用隨機選擇的映射2?

非常感謝。

回答

9

我想最簡單的方法是使functools.partial使用,它允許您創建一個「部分評價」功能:

from functools import partial 

def evaluate(match, mappings): 
    return str(eval(match.group(0)[2:-1], mappings)) 

mappings = {'A': 1, 'B': 2} # Or whatever ... 

newstring = sub(r'\#\{([^#]+)\}', partial(evaluate, mappings=mappings), string) 
+0

請注意:如果您顛倒了'evaluate'參數的順序,您可以說'partial(evaluate,mappings)'。 – tzot 2010-07-11 09:02:59

+1

是的,但我故意使用了參數順序,因爲對我來說,以這種方式定義'evaluate()'會更自然,我想展示partial()的靈活性。 – 2010-07-11 13:30:10

1

你可以使用一個函數對象。

class A(object): 
    def __init__(self, mappings): 
    self.mappings = mappings 
    def __call__(self, match): 
    return str(eval(match.group(0)[2:-1], self.mappings)) 

evaluate = A({'A': 1, 'B': 2}) 
2

您可以創建一個封閉。

def evaluator(mappings): 
    def f(match): 
    return str(eval(match.group(0)[2:-1], mappings)) 
    return f 

evaluate = evaluator({'A': 1, 'B': 2}) 

由於f只是一個單獨的語句,你可以簡單地使用lambda

def evaluator(mappings): 
    return lambda match: str(eval(match.group(0)[2:-1], mappings)) 
0

的變體,我會建議:

mappings = {'A': 1, 'B': 2} # Or whatever ... 
def evaluate(match): 
    return str(eval(match.group(0)[2:-1], mappings)) 
newstring = sub(r'\#\{([^#]+)\}', evaluate, string) 

即簡單地把def evaluate(..)只是sub()前作爲本地功能。