Index: Doc/library/string.rst =================================================================== --- Doc/library/string.rst (révision 88911) +++ Doc/library/string.rst (copie de travail) @@ -650,9 +650,10 @@ these rules. The methods of :class:`Template` are: -.. class:: Template(template) +.. class:: Template(template, default=None) - The constructor takes a single argument which is the template string. + The constructor takes two arguments, the first is the template string and + the second (optional) is a mapping which gives default values. .. method:: substitute(mapping, **kwds) @@ -667,10 +668,11 @@ .. method:: safe_substitute(mapping, **kwds) Like :meth:`substitute`, except that if placeholders are missing from - *mapping* and *kwds*, instead of raising a :exc:`KeyError` exception, the - original placeholder will appear in the resulting string intact. Also, - unlike with :meth:`substitute`, any other appearances of the ``$`` will - simply return ``$`` instead of raising :exc:`ValueError`. + *mapping*, *kwds* and the default values given to the constructor, + instead of raising a :exc:`KeyError` exception, the original placeholder + will appear in the resulting string intact. Also, unlike with + :meth:`substitute`, any other appearances of the ``$`` will simply + return ``$`` instead of raising :exc:`ValueError`. While other exceptions may still occur, this method is called "safe" because substitutions always tries to return a usable string instead of @@ -679,17 +681,24 @@ templates containing dangling delimiters, unmatched braces, or placeholders that are not valid Python identifiers. - :class:`Template` instances also provide one public data attribute: + :class:`Template` instances also provide two public data attributes: .. attribute:: template This is the object passed to the constructor's *template* argument. In general, you shouldn't change it, but read-only access is not enforced. + + .. attribute:: default + + This is the optional mapping passed as the *default* argument to the + contructor. Here is an example of how to use a Template: >>> from string import Template - >>> s = Template('$who likes $what') + >>> s = Template('$who likes $what', default={"who":"dennis"}) + >>> s.substitute(what='vanilla cakes') + 'dennis likes vanilla cakes' >>> s.substitute(who='tim', what='kung pao') 'tim likes kung pao' >>> d = dict(who='tim') @@ -703,6 +712,8 @@ KeyError: 'what' >>> Template('$who likes $what').safe_substitute(d) 'tim likes $what' + >>> Template('$who likes $what', default={"what":"red cars"}).substitute(d) + 'tim likes red cars' Advanced usage: you can derive subclasses of :class:`Template` to customize the placeholder syntax, delimiter character, or the entire regular expression used Index: Lib/string.py =================================================================== --- Lib/string.py (révision 88911) +++ Lib/string.py (copie de travail) @@ -77,8 +77,9 @@ idpattern = r'[_a-z][_a-z0-9]*' flags = _re.IGNORECASE - def __init__(self, template): + def __init__(self, template, default=None): self.template = template + self.default = default if default is not None else {} # Search for $$, $identifier, ${identifier}, and any bare $'s @@ -97,12 +98,14 @@ def substitute(self, *args, **kws): if len(args) > 1: raise TypeError('Too many positional arguments') + + mapping = self.default if not args: - mapping = kws + mapping.update(kws) elif kws: - mapping = ChainMap(kws, args[0]) + mapping.update(ChainMap(kws, args[0])) else: - mapping = args[0] + mapping.update(args[0]) # Helper function for .sub() def convert(mo): # Check the most common path first.