[Python-ideas] Escaped braces in format specifiers
Ken Kundert
python-ideas at shalmirane.com
Tue May 15 02:41:36 EDT 2018
The syntax for formatted string literals is given here:
https://docs.python.org/3/reference/lexical_analysis.html#f-strings
If you were to examine this carefully, you would see that a format_spec (the
part within the braces but after the colon) can be empty or it can consist of
literal characters and replacement fields. For example:
f"result: {value:{width}.{precision}}"
In this case '{width}.{precision}' is the format_spec, it consists of two
replacement fields, {width} and {precision}, and one literal character, '.'.
The definition of literal character includes all characters except braces.
Presumably excluding braces makes it easier to distinguish the replacement
fields. However, replacement fields are also used in the f_string itself, but
in that case escaped braces are explicitly added to the list of valid symbols.
I think the fact that one cannot include braces in the format_spec is an
unnecessary and undesirable restriction.
As an example of where it would be useful to allow braces in the format_spec,
consider this simple example:
>>> class mydict(dict):
... def __format__(self, template):
... return ''.join(
... template.format(v, k=k, v=v) for k, v in self.items()
... )
>>> accounts = mydict(checking=4256.78, savings=12000, brokerage=24685.5)
>>> print('Accounts:\n {0:{{k:>9s}}: ${{v:>9,.2f}}\n }'.format(accounts))
Accounts:
checking: $ 4,256.78
savings: $12,000.00
brokerage: $24,685.50
In this example, the format_spec is itself treated as a format string, which
allows a recursive specification of the string format.
If you try this example in Python3.6 you will find that it works, but it should
not because the format_spec contains escaped braces. However, the fact that it
works appears be be a happy accident. Things break if the escaped braces are not
balanced (thanks to Thomas Jollans for finding this). Furthermore, things break
in a different manner when an f-string is used. For example:
>>> print(f'Accounts:\n {accounts:{{k:>9s}}: ${{v:>9,.2f}}\n }')
File "<fstring>", line 1
({k:>9s})
^
SyntaxError: invalid syntax
or:
>>> print(f'Accounts:\n {accounts:{{k}}: ${{v}}\n }')
File "tryit", line 12, in <module>
print(f'Accounts:\n {accounts:{{k}}: ${{v}}\n }')
NameError: name 'k' is not defined
Oddly, the f-string still raises the NameError even if both k and v are
explicitly defined.
At a minimum it would be good to improve the error messages that are produced
when escaped braces are included in the format_spec. Most of the error messages
that are given, if they are given at all, are misleading. None are as simple as:
SyntaxError: escaped braces are not allowed in a format spec.
But rather than improve the error messages, I think we should consider simply
allowing escaped braces in the format_spec. Doing so enables the neat idea of
recursive format strings. But even if you don't like that idea, it would be nice
to remove this rather rather odd restriction and would make the behavior of
f-strings and the format method more consistent.
-Ken
More information about the Python-ideas
mailing list