473,382 Members | 1,290 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

yet another recipe on string interpolation

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?

Michele Simionato
Jul 18 '05 #1
8 1751
Michele Simionato wrote:
I was playing with string.Template in Python 2.4 and I came out with the
following recipe:

def merge(*dictionaries):
"""Merge from right (i.e. the rightmost dictionary has the precedence).""" Do you have any comments? Suggestions for improvements?


My only comment is about *your* comment, above. I would
have called the behaviour described "merge from left".
Maybe best just to cut out that part of the comment, and
leave it as "merge where rightmost dictionary has precedence".

Cute recipe though. :-)

-Peter
Jul 18 '05 #2
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

Jul 18 '05 #3
Peter Hansen <pe***@engcorp.com> wrote in message news:<Nr********************@powergate.ca>...
My only comment is about *your* comment, above. I would
have called the behaviour described "merge from left".
Maybe best just to cut out that part of the comment, and
leave it as "merge where rightmost dictionary has precedence".
Ok.
Cute recipe though. :-)


Thanks ;-)

I was asking for comments about the performance of this approach
and/or design choices: for instance, in the case an explicit
dictionary is passed, it could make sense to use it for interpolation,
without merging it with the locals and globals. I could add a default
argument to set this behavior, but I am not sure if this is worthwhile ...

Michele Simionato
Jul 18 '05 #4
Michele Simionato wrote:
language="Python"
print interp("My favorite language is $language.")

Do you have any comments? Suggestions for improvements?


Well, for what it attempts to do, I'd say your solution is ideal.
However, I think that Ka-Ping Yee's implementation was more full-featured:

http://lfw.org/python/Itpl20.py

Of course, this goes above and beyond the functionality of Template, so
your code example is orthogonal to the reasons I'd prefer his solution.

He did the same sort of stack trick that you're doing, also. This code
was the first that I'd ever seen do it, and this was before
sys._getframe() was available.

Dave
Jul 18 '05 #5
"Michele Simionato":
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)


The ASPN chainmap() recipe is an alternative to merge(). It spares the initial
effort of combining all the dictionaries. Instead, it does the lookups only
when a specific key is needed. In your example, it is likely that most of
globals will never be looked-up by the template, so the just-in-time approach
will save time and space. Also, chainmap() is a bit more general and will work
with any object defining __getitem__.

The interp() part of the recipe is nice.
Raymond Hettinger
http://aspn.activestate.com/ASPN/Coo.../Recipe/305268 :
--------- chainmap() ---------
import UserDict

class Chainmap(UserDict.DictMixin):
"""Combine multiple mappings for sequential lookup.

For example, to emulate Python's normal lookup sequence:

import __builtin__
pylookup = Chainmap(locals(), globals(), vars(__builtin__))
"""

def __init__(self, *maps):
self._maps = maps

def __getitem__(self, key):
for mapping in self._maps:
try:
return mapping[key]
except KeyError:
pass
raise KeyError(key)
Raymond Hettinger
Jul 18 '05 #6
Peter Otten <__*******@web.de> wrote in message news:<cm*************@news.t-online.com>...
As of 2.4b2, the modulo operator is not (not yet, or no longer?) defined, so
I had to use substitute() instead.


I have downloaded Python 2.4b2 today and looked at the source code for
the Template class. There is no __mod__ method, in contraddiction with
PEP 292. Is there somebody who knows what happened and the rationale
for the change? Should PEP 292 be updated?

Michele Simionato
Jul 18 '05 #7
"Michele Simionato" <mi***************@gmail.com> wrote in message
news:4e**************************@posting.google.c om...
Peter Otten <__*******@web.de> wrote in message news:<cm*************@news.t-online.com>...
As of 2.4b2, the modulo operator is not (not yet, or no longer?) defined, so
I had to use substitute() instead.


I have downloaded Python 2.4b2 today and looked at the source code for
the Template class. There is no __mod__ method, in contraddiction with
PEP 292. Is there somebody who knows what happened and the rationale
for the change? Should PEP 292 be updated?


It was updated a good while ago:
http://www.python.org/peps/pep-0292.html

The PEP STATES that the API is through the substitute() and safe_substitute()
methods. Also, it notes that __mod__ is easily aliased to one of the those via
a Template subclass.

By using named methods instead of the % operator:
* we avoid the precedence issues associated with %
* we avoid confusion as to whether a tuple is an acceptable second argument
* we avoid confusion with "%s" style inputs.
* we enable keyword arguments: mytempl.substitute(weather="rainy")
* we get something more documenting than punctuation.
Raymond Hettinger


Michele Simionato

Jul 18 '05 #8
> By using named methods instead of the % operator:
* we avoid the precedence issues associated with %
* we avoid confusion as to whether a tuple is an acceptable second argument
* we avoid confusion with "%s" style inputs.
* we enable keyword arguments: mytempl.substitute(weather="rainy")
* we get something more documenting than punctuation.


s/documenting/self-documenting
One other thought. In both the original and current design, it is possible and
perhaps likely that the template instantiation and method application will be
remote from one another. Unfortunately, the original design forced the
safe/non-safe decision to be made at the time of instantiation.

When you think about it, that was a mis-assignment of responsibilities. The
choice of safe vs. non-safe has nothing to do with the contents of the template
and everything to do with how the template is used. The code that uses the
template (applies the method) needs to know whether it should handle exceptions
or not. Hence, it should be the one to make the safe / non-safe choice.

Consider whether the following fragment is correct:

mytemp % values

Should it have been wrapped in a try/except? Can values be a tuple? Do we have
a reasonable expectation of whether mytemp contains $placeholder ro
%(placeholder)s? The approach taken by the revised pep makes all of the issues
clear.

There were a couple of downsides to switching the API. Formerly, if you knew
that client code used the % operator with a dictionary, then you could pass in
an instance of the Template class and have it do the right thing (polymorphism
on a good day). Also, most folks already know what % means, so there was less
of a learning curve. IOW, the switch was an improvement, but not a pure win.
C'est le vie.
Raymond Hettinger
Jul 18 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Paul Rubin | last post by:
How about adding a string interpolation method and a some print methods to strings. 'hello world'.print() => same as "print 'hello world'". With optional fd arg, print to file object 'hello...
12
by: Eli Daniel | last post by:
Hi, I'm new to Python. Can you please tell me if the following is possible. My users are using other scripting launguage to write scripts. They are used to write somthing like (keeping it...
2
by: Michele Simionato | last post by:
This is somewhat in between a bug report and a feature request. I was using the new string.Template class and I have run into a few issues that I traced back to the usage of the idiom '%s' % val...
14
by: Charles Banas | last post by:
I'm not sure if this is the right place to ask about this, but I've seen several posts in the past regarding Akima's Bivariate Interpolations routines, and i'm wondering if someone can give me some...
3
by: Jonas Ernst | last post by:
Hi, Can somebody give me some hints how to do a line interpolation without using floating point arithemtics? The function shall do a linear interpolation between 2 points (line interp?) and...
2
by: Kun | last post by:
I have an html form that takes dates and inserts them into a mysql file. Currently, users have to type in dates in the yyyy-mm-dd format. As of now, this process works with the sql. However, I...
5
by: linnorm | last post by:
I've got a bit of code which has a dictionary nested within another dictionary. I'm trying to print out specific values from the inner dict in a formatted string and I'm running into a roadblock. ...
5
by: xandra | last post by:
i understood the concept of interpolation search. but i couldn't understand what would be the steps for that search. for example, if i'm searching for J in this file A A B E F H J M N N N N O P P...
1
by: Thomas | last post by:
Hi list! I'm struggling with a recipe from the Python Cookbook (2nd ed.) concerning XML-RPC. It's recipe 15.2 "Serving XML-RPC Requests", and since I thought it's a popular book some other folks...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.