Python Template String Formatting Method | by Vinicius Monteiro | Towards Data Science

Template string is another method used to format strings in Python. In comparison with %operator, .format() and f-strings, it has a (arguably) simpler syntax and functionality. It’s ideal for internationalization (i18n), and there are some nuances that you may find advantageous—especially when working with regular expressions (regex).
Let’s first see the syntax of the other three, so we can compare.
>>> name = "Alfredo">>> age = 40>>> "Hello, %s. You are %s." % (name, age)'Hello, Alfredo. You are 40.'
>>> print('The {} {} {}'.format('car','yellow','fast')) #empty bracesThe car yellow fast>>> print('The {2} {1} {0}'.format('car','yellow','fast')) #indexThe fast yellow car>>> print('The {f} {y} {c}'.format(c='car',y='yellow',f='fast')) #keywordsThe fast yellow car
>>> name = "Peter">>> print(f'Nice to meet you, {name}')
It uses Template class from string module. It has a syntax somewhat similar to .format() when done with keywords, but instead of curly braces to define the placeholder, it utilises a dollar sign ($). ${} is also valid and should be in place when a valid string comes after the placeholder.
See the syntax for various situations. I’ll begin explaining safe_substitute and the use with regex.
Imagine you want to replace something in a string that contains {}, % and $. It can happen when working with regular expression.
Consider an input field that accepts company stock symbol plus positive (+) or negative (-) values in percentages and nothing afterwards. And symbol plus +- is dynamically replaced. Such as: AAPL: +20% or TSLA: -5% (Perhaps it’s a silly use case, I know! but please ignore. It’s just an example).
Regex: (([symbol: + or -][0–9]{1,4}[%])$)
For % operator, .format() and f-string — it doesn’twork. % operator and .format() raises an error and f-strings removes {m,n}. See below
#% operator>>> print('(([%s][0-9]{1,4}[%])$)' % "AAPL: -")TypeError: not enough arguments for format string#.format()>>> print('(([{symbol_pos_neg}][0-9]{1,4}[%])$)'.format(symbol_pos_neg = 'AAPL: +'))KeyError: '1,4'#f-strings>>> symbol_pos_neg = "AAPL: +">>> print(f'(([{symbol_pos_neg}][0-9]{1,4}[%])$)')(([AAPL: +][0-9](1, 4)[%])$)
Although it can be easily solved by escaping the characters (doubling the curly braces or percentage sign), I find it inconvenient. With Template string, you don’t need to do that. {} and % are not used to define placeholders, and by using safe_substitute, you’re not enforced to replace all $.
See below, the regex is unchanged and $symbol_pos_neg is replaced correctly.
>>> print(Template('(([$symbol_pos_neg][0-9]{1,4}[%])$)').safe_substitute(symbol_pos_neg='AAPL: -'))(([AAPL: -][0-9]{1,4}[%])$)
>>> from string import Template>>> Template('$obj is $colour').substitute(obj='Car',colour='red')'Car is red'
>>> d = dict(obj='Car')>>> Template('$obj is red').substitute(d)'Car is red'
If there is an invalid string after the placeholder, only the placeholder is considered. Example, see the ‘.’ (dot) after $who. It’s printed as normal.
>>> from string import Template>>> Template('$obj. is $colour').substitute(obj='Car',colour='red')'Car. is red'
If valid characters follow the placeholder, it must be enclosed in curly braces.
>>> from string import Template>>> Template('${noun}ification').substitute(noun='Ident')'Identification'
To note, characters such as underscore (_) is also considered valid. So the same rule to use ${} applies.
The substitution is done as normal, and one extra $ is printed.
>>> Template(’$obj. is $$$colour’).substitute(obj=’Car’,colour=’red’)'Car. is $red'
I’m still a beginner in Python and comparing String formatting methods taught me a lot. I hope I was clear in providing the details to you. Despite Template string being less powerful:
viniciusmonteiro$ python3 -m timeit -s "x = 'f'; y = 'z'" "f'{x} {y}'"5000000 loops, best of 5: 82.5 nsec per loopviniciusmonteiro$ python3 -m timeit -s "from string import Template; x = 'f'; y = 'z'" "Template('$x $y').substitute(x=x, y=y)"  # template string500000 loops, best of 5: 752 nsec per loop
I think it brings some benefit in terms of simplicity and convenience in some cases. Although I understand these can be subjective.
[1] string — Common string operations https://docs.python.org/3/library/string.html#template-strings
[2] Python 3’s f-Strings: An Improved String Formatting Syntax (Guide) https://realpython.com/python-f-strings/
[3] Performance of different string concatenation methods in Python — why f-strings are awesome https://grski.pl/fstrings-performance.html