Welcome, guest | Sign In | My Account | Store | Cart

A lightweight and powerful way to evaluate expressions embedded in strings during interpolation.

Python, 26 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class InterpolationEvaluationException(KeyError):
    pass 

class expression_dictionary(dict):
    def __getitem__(self, key):
        try:
            return dict.__getitem__(self, key)
        except KeyError:
            try:
                return eval(key,self)
            except Exception, e:
                raise InterpolationEvaluationException(key, e)


# ---------- Usage ---------------

# Evaluate expressions in the context of a dictionary...
>>> my_dict = {'x': 1, 'y': 2}
>>> print "The sum of %(x)s and %(y)s is %(x+y)s" % expression_dictionary(my_dict)
  The sum of 1 and 2 is 3

# or use in conjunction with locals() or globals() to evaluate in a namespace.
>>> ft = 14410.0
>>> ns = expression_dictionary(locals())
>>> print "  Summit altitude: %(ft)0.1f feet (%(ft * 0.3048)0.1f meters)" % ns
  Summit altitude: 14410.0 feet (4392.2 meters)

Standard Python string interpolation allows elements of a dictionary to be interpolated with the "%(key)F" syntax, where F is a format code. Hence, the expression:

"Hello, %(greetee)s." % {'greetee':'WORLD'}

evaluates as =>

"Hello, WORLD."

It is often desirable to manipulate the contents of the dictionary in some way before interpolating. The usual approach is to make another key/value pair containing the modified value:

d = {'greetee':'WORLD'} d['lower_case_greetee'] = d['greetee'].lower() "Hello, %(lower_case_greetee)s." % d

=>

"Hello, world."

But this is tedious. Wouldn't it be nice to perform inline manipulations immediately before interpolating?

"Hello, %(greetee.lower())s." % {'greetee':'WORLD'}

=> "Hello, world."


Well, now you can. Hooray. Any dictionary-like object, wrapped in the expression_dictionary class, will run eval() on expressions.

The advanced Pythonistas in the audience might point out, quite correctly, that the expression_dictionary class actually has nothing to do specifically with string interpolation. Indeed, it could be used for anything...

>>> d = evaluation_dictionary()
>>> d['x'] = 10
>>> d['y'] = 20
>>> print d['x + y']
30

... but the author feels it is most useful for interpolation.

Advantages: + Uses standard string interpolation syntax + Does not require modified string classes + Simple + Adequate for most light-weight templating needs

Disadvantages: - May be slow if used with large namespaces - Insecure by design (because it uses eval)... NEVER allow arbitrary or untrusted expressions to be evaluated,e.g. %(__import__('os').remove('/my/file'))s - Slower than a dict for normal keyword lookup (because they go through eval)

Created by Lonnie Princehouse on Thu, 13 Jul 2006 (PSF)
Python recipes (4591)
Lonnie Princehouse's recipes (5)
Bookmarks (2)

Required Modules

  • (none specified)

Other Information and Tasks