yet another recipe on string interpolation

Peter Otten __peter__ at web.de
Thu Nov 4 13:39:04 EST 2004


Michele Simionato wrote:

> I was playing with string.Template in Python 2.4 and I came out with the
> following recipe:
> 
> import sys
> from string import Template
> 
> def merge(*dictionaries):
>     """Merge from right (i.e. the rightmost dictionary has the
>     precedence).""" merg = {}
>     for d in dictionaries:
>         merg.update(d)
>     return merg
> 
> def interp(s, dic = None):
>     if dic is None: dic = {}
>     caller = sys._getframe(1)
>     return Template(s) % merge(caller.f_globals, caller.f_locals, dic)
> 
> language="Python"
> print interp("My favorite language is $language.")
> 
> Do you have any comments? Suggestions for improvements?

Nice. recipe. I think the perlish format looks better than our current
"%(name)s" thingy. While interp() does some magic it should still be
acceptable for its similarity with eval(). Here are some ideas:
You could virtualize the merger of dictionaries:

class merge(object):
    def __init__(self, *dicts):
        self.dicts = dicts
    def __getitem__(self, key):
        for d in reversed(self.dicts):
            try:
                return d[key]
            except KeyError:
                pass
        raise KeyError(key)

I would use either implicitly or explicitly specified dictionaries, not
both:
        
def interp(s, *dicts, **kw):
    if not dicts:
        caller = sys._getframe(1)
        dicts = (caller.f_globals, caller.f_locals)
    return Template(s).substitute(merge(*dicts), **kw)

As of 2.4b2, the modulo operator is not (not yet, or no longer?) defined, so
I had to use substitute() instead.

I really like your option to provide multiple dictionaries - maybe you
should suggest changing the signature of the substitute() method to the
author of the Template class.

Peter






More information about the Python-list mailing list