[Python-Dev] Re: Alternative Implementation for PEP 292:Simple String Substitutions (original) (raw)

Tim Peters tim.peters at gmail.com
Sun Sep 5 06:32:33 CEST 2004


[Paul Moore]

Would it be useful to factor out the "identifier syntax" bit of the pattern? The "escaped" and "bogus" groups are less likely to need changing than what constitutes an identifier.

[Barry Warsaw]

And if they did, you'd want to change them both at the same time. Do you have any ideas for an efficient, easily documented implementation?

You'll rarely hear me say this , but fiddling classes at class creation time is exactly what metaclasses are for. For example, suppose you said a Template subclass could define a class variable idpat, containing a regexp matching that subclass's idea of "an identifier".

Then we could define a metaclass once-and-for-all, like so:

class _TemplateFiddler(type):

pattern = r"""
    (?P<escaped>\${2})|     # Escape sequence of two $ signs
    \$(?P<named>%s)|        # $ and a Python identifier
    \${(?P<braced>%s)}|     # $ and a brace delimited identifier
    (?P<bogus>\$)           # Other ill-formed $ expressions
"""

def __init__(cls, name, bases, dct):
    super(_TemplateFiddler, cls).__init__(name, bases, dct)
    idpat = cls.idpat
    cls.pattern = _re.compile(_TemplateFiddler.pattern % (idpat, idpat),
                              _re.IGNORECASE | _re.VERBOSE)

That substitutes the idpat regexp into the base pattern in two spots, compiles it, and attaches the result as the pattern attribute of the class being defined.

The definition of Template changes like so:

class Template(unicode): # same """A string class for supporting $-substitutions.""" # same

__metaclass__ = _TemplateFiddler  # this is new
__slots__ = [] # same

idpat = r'[_a-z][_a-z0-9]*'  # this repaces the current `pattern`

# The rest is the same.

While the implementation relies on understanding metaclasses, users don't have to know about that. The docs are easy ("define a class vrbl idpat"), and it's as efficient as if subclasses had compiled the full regexp themselves. Indeed, you can do any amount of computation once in the metaclass init, and cache the results in attributes of the class.



More information about the Python-Dev mailing list