Search code examples
pythonoopdeep-copypyprocessing

Constructing a instance variable pyparsing matcher from class variable elements


With pyparsing I construct a complex matcher object which is suppose to match slightly different things depending on a instantiation flag. Here a (simplified) example:

class MyMatcher():

    def __init__( self, special_flag = False):
        self.special_flag = special_flag

        a = pp.Word(pp.alphas)('A')
        if self.special_flag:
            b = pp.Word(pp.alphas)('B')
        else:
            b = pp.Word(pp.nums)('B')
        c = pp.Word(pp.alphas)('C')
        # d = ...
        # e = ...
        # ...

        self.expr = (a + b | b ) + pp.Optional(c) # + ...

    def parse(self, s):
        return self.expr.parseString(s, parseAll=True)

a, b, c,.... are class variables, so that I can reference them in expr just like that and do not have to prefix them with the instance reference self (like in self.a). expr has to be an instance variable because different instantiations of MyMatcher have to match different things.

The above example works:

mymTrue = MyMatcher(True)
mymFalse = MyMatcher(False)
print (mymTrue.parse("alpha aaaa alpha"))
print (mymFalse.parse("alpha 777 alpha"))

returns as expected:

['alpha', 'aaaa', 'alpha']
['alpha', '777', 'alpha']

My worry is: Does this work even for very complex matchers with lots of (nested) a, b, c, d, etc... ? Or phrased differently: Is the full logic (deep-)copied from the class variables to the instance object expr, so that it doesn't matter that the a, b and c get overwritten on the next MyMatcher object creation?

Or if this is a problem, is there another way to create varying matchers with short and beautiful construction like (a + b | b ) + pp.Optional(c)?


Solution

  • The variables a, b, c,.... are not class variables; they are local variables in the __init__ method. References to these variables will be kept alive as long as needed. (See in the Python documentation Scopes and Namespaces in Classes.)