How to pass a variable to a re.sub callback?

后端 未结 4 1104
南笙
南笙 2021-02-09 08:29

I am using a re.sub callback to replace substrings with random values, but I would like the random values to be the same across different strings. Since the re.sub callback does

相关标签:
4条回答
  • 2021-02-09 09:09

    You could use a function object.

     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})
    
    0 讨论(0)
  • 2021-02-09 09:14

    You could create a closure.

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

    Since f is just a single statement, you could simply use lambda:

    def evaluator(mappings):
      return lambda match: str(eval(match.group(0)[2:-1], mappings))
    
    0 讨论(0)
  • 2021-02-09 09:16

    The variant I would recommend:

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

    i.e. simply put the def evaluate(..) just before the sub(), as a local function.

    0 讨论(0)
  • 2021-02-09 09:20

    The easiest way I guess is to make use of functools.partial, which allows you create a "partially evaluated" function:

    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 讨论(0)
提交回复
热议问题