[Python-ideas] Escaped braces in format specifiers

Eric V. Smith eric at trueblade.com
Tue May 15 16:23:26 EDT 2018


I'm busy at the sprints, so I don't have a lot of time to think about this.

However, let me just say that recursive format specs are supported, to a 
depth of 1.

 >>> width=10
 >>> f'{"test":{width}}'
'test      '

So first the string is basically expanded to:
f'{"test":10}'
Then the string is formatted again to produce the final result.

That is why the braces must match: they're being used for recursive 
format specs. There's no mechanism for having braces that aren't 
inspected by the f-string machinery.

Eric

On 5/15/18 2:41 AM, Ken Kundert wrote:
> 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
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>


More information about the Python-ideas mailing list