ASPN ActiveState Programmer Network  
ActiveState, a division of Sophos
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups
Submit Recipe
My Recipes

All Recipes
All Cookbooks


View by Category

Title: String Interpolation with Evaluation of Embedded Expressions
Submitter: Lonnie Princehouse (other recipes)
Last Updated: 2006/07/13
Version no: 1.0
Category: Text

 

3 stars 1 vote(s)


Description:

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

Source: Text Source

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)

Discussion:

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)



Add comment

No comments.



Highest rated recipes:

1. Implementation of sets ...

2. bag collection class

3. deque collection class

4. Floating Point Simulator

5. HTML colors to/from RGB ...

6. Select the nth smallest ...

7. Function Decorators by ...

8. MS SQL Server log monitor

9. Table objects with ...

10. wx twisted support using ...




Privacy Policy | Email Opt-out | Feedback | Syndication
© 2006 ActiveState Software Inc. All rights reserved.