Escaped braces in format specifiers
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
participants (3)
-
Eric V. Smith
-
Ken Kundert
-
Nick Coghlan