[Python-Dev] string.Template format enhancements (Re: Replacement for print in Python 3.0)

Nick Coghlan ncoghlan at gmail.com
Tue Sep 6 16:07:01 CEST 2005

tanzer at swing.co.at wrote:
> Positional arguments remove too much meaning from the template.
> Compare:
>   '$user forgot to frobnicate the $file!\n'
> with
>   '$1 forgot to frobnicate the $2!\n'
> Whenever the template definition and its use are not directly
> adjacent, the template is that much harder to understand (i.e.,
> in the context of translation, one wouldn't see the arguments
> passed to the template).

Ideas like this one are really about taking the current C-originated string 
formatting and replacing it with a more powerful version of the new 
string.Template formatting.

One interesting idea to consider is to add "format" and "safe_format" string 
methods (or "substitute" and "safe_substitute" if matching the PEP 292 method 
names is considered important) which work something like:

   # These would be new str and unicode methods
   def format(*args, **kwds):
       return string.Template(args[0]).substitute(*args[1:], **kwds)

   def safe_format(*args, **kwds):
       return string.Template(args[0]).safe_substitute(*args[1:], **kwds)

Then enhance string.Template such that:

   1. Item identifiers could be numbers as well as valid Python identifiers
   2. Positional arguments were added to the dictionary of items using their 
argument index as a string

Something like:

   # This would be modified behaviour of the substitute method
   # rather than a separate method or function
   def pos_substitute(*args, **kwds):
       self = args[0]
       kwds.update((str(idx), arg) for idx, arg in enumerate(args))
       # Avoiding including self in kwds is also an option
       return self.substitute(**kwds)

(To try this on Py2.4, use "$p1" for the positional arguments to easily get 
around the restriction in the string.Template regex)

With the above changes, the following would work:
   "$1: $2".format("Number of bees", "0.5")
And produce:
   "Number of bees: 0.5"

When pre-compiling string.Templates, the keyword method is significantly 
clearer, but if the syntax was accessible through a string method, then being 
able to use positional arguments would be very handy.

At this point, the only thing missing is the ability to handle proper output 
formatting - that would need to be done by invoking the string mod operator 
directly on the positional argument via:

   "$1: $2".format("Number of bees: ", "%0.2f" % val)

In theory (I haven't really tried this bit), it should be possible to adjust 
string.Template to support the following equivalent:

   "$1: $[0.2f]2".format("Number of bees: ", val)

That way, rather than inventing a new formatting language, string.Template 
could leverage the existing string mod operator by substituting the result of 
"('%' + fmt) % val" wherever it sees "$[fmt]name" or "$[fmt]{name}"


Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia

More information about the Python-Dev mailing list