This might be necessary if you, for example, want to apply your own set of replacements to a string argument that will be passed to you by another mechanism that applies its own set of replacements.
This example supposes that you might want to use square-brackets instead of the standard curly-brackets.
import string import re _FIELD_RE = re.compile(r'\[([a-zA-Z0-9_]+)\]') class CustomReplacer(string.Formatter): def parse(self, s): last_stop_index = None for m in _FIELD_RE.finditer(s): token_name = m.group(1) start_index, stop_index = m.span() if start_index == 0: prefix_fragment = '' elif last_stop_index is None: prefix_fragment = s[:start_index] else: prefix_fragment = s[last_stop_index:start_index] last_stop_index = stop_index yield prefix_fragment, token_name, '', None cr = CustomReplacer() template = 'aa [name] bb [name2] cc dd [name3]' replacements = { 'name': 'howard', 'name2': 'mark', 'name3': 'james', } output = cr.format(template, **replacements) print(output)
Output:
aa howard bb mark cc dd james
Note that no formatting is supported with our custom replacer (though it could be added, with more work). If any formatting specifiers are provided, they will fail the regular-expression match and be ignored.