如何将变量传递给re.sub回调?

时间:2010-07-10 07:26:39

标签: python regex callback

我使用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”。但是我希望能够随机选择值,并且仍然可以在两个字符串中替换它们。这将涉及删除'evaluate'中的'mappings'行,并使用类似两条注释行的内容。但是,如果我不能在re.sub回调函数中将其作为参数传递,那么在评估两个字符串时如何使用随机选择的映射2?

非常感谢。

4 个答案:

答案 0 :(得分:10)

我猜最简单的方法是使用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)

答案 1 :(得分: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))

答案 2 :(得分: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})

答案 3 :(得分: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()之前,作为本地函数。