Recipe 1.17. Interpolating Variables in a Stringin Python 2.4
Credit: John Nielsen, Lawrence Oluyede, Nick
Coghlan
Problem
Using Python 2.4, you need a simple way to get a copy of a string
where specially marked identifiers are replaced with the results of
looking up the identifiers in a dictionary.
Solution
Python 2.4 offers the new string.Template class
for this purpose. Here is a snippet of code showing how to use that
class: import string
# make a template from a string where some identifiers are marked with $
new_style = string.Template('this is $thing')
# use the substitute method of the template with a dictionary argument:
print new_style.substitute({'thing':5}) # emits: this is 5
print new_style.substitute({'thing':'test'}) # emits: this is test
# alternatively, you can pass keyword-arguments to 'substitute':
print new_style.substitute(thing=5) # emits: this is 5
print new_style.substitute(thing='test') # emits: this is test
Discussion
In Python 2.3, a format string for identifier-substitution has to be
expressed in a less simple format: old_style = 'this is %(thing)s' with the identifier in parentheses after a %, and
an s right after the closed parenthesis. Then, you
use the % operator, with the format string on the
left of the operator, and a dictionary on the
right: print old_style % {'thing':5} # emits: this is 5
print old_style % {'thing':'test'} # emits: this is test Of course, this code keeps working in Python 2.4, too. However, the
new string.Template class offers a simpler
alternative. When you build a string.Template instance, you may
include a dollar sign ($) by doubling it, and you
may have the interpolated identifier immediately followed by letters
or digits by enclosing it in curly braces ({ }).
Here is an example that requires both of these refinements: form_letter = '''Dear $customer,
I hope you are having a great time.
If you do not find Room $room to your satisfaction,
let us know. Please accept this $$5 coupon.
Sincerely,
$manager
${name}Inn'''
letter_template = string.Template(form_letter)
print letter_template.substitute({'name':'Sleepy', 'customer':'Fred Smith',
'manager':'Barney Mills', 'room':307,
}) This snippet emits the following output: Dear Fred Smith,
I hope you are having a great time.
If you do not find Room 307 to your satisfaction,
let us know. Please accept this $5 coupon.
Sincerely,
Barney Mills
SleepyInn Sometimes,
the handiest way to prepare a dictionary to be used as the argument
to the substitute method is to set local
variables, and then pass as the argument locals( )
(the artificial dictionary whose keys are the local variables, each
with its value associated): msg = string.Template('the square of $number is $square')
for number in range(10):
square = number * number
print msg.substitute(locals( )) Another handy alternative is to pass the values to substitute using
keyword argument syntax rather than a dictionary: msg = string.Template('the square of $number is $square')
for i in range(10):
print msg.substitute(number=i, square=i*i) You can even pass both a dictionary and keyword
arguments: msg = string.Template('the square of $number is $square')
for number in range(10):
print msg.substitute(locals( ), square=number*number) In case of any conflict between entries in the dictionary and the
values explicitly passed as keyword arguments, the keyword arguments
take precedence. For example: msg = string.Template('an $adj $msg')
adj = 'interesting'
print msg.substitute(locals( ), msg='message')
# emits an interesting message
See Also
Library Reference docs for
string.Template (2.4 only) and the
locals built-in function. |