[Python-ideas] Escaped braces in format specifiers
Ken Kundert
python-ideas at shalmirane.com
Sat May 19 01:56:54 EDT 2018
On Tue, May 15, 2018 at 04:23:26PM -0400, Eric V. Smith wrote:
> 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
Eric,
You say that recursive format specs are supported to a depth of 1, but it
does not seem like true recursion to me. If it were true recursion, wouldn't the
escaped braces be interpreted properly inside the format spec, just as they are
in the literal portion of the f-string?
Is there some reason why escaped braces are not supported in the format specs?
Consider the following example:
>>> class myclass:
... def __format__(self, fmt_spec):
... return 'fmt_spec: ' + fmt_spec
>>> d = myclass()
>>> x = 3
>>> print('1: ext={{x}} {d:int={{x}}}'.format(d=d))
1: ext={x} fmt_spec: int={x}
>>> print(f'2: ext={{x}} {d:int={{x}}}')
2: ext={x} fmt_spec: int={3}
>>> print(f'3: ext={set([x])} {d:int={set([x])}}')
3: ext={3} fmt_spec: int={3}
In each case, the same substring is found in the literal portion (ext) of the
format string and in the format spec (int).
In case 1, the format string is passed to a format method and the substring is
{{x}}. In both cases, the double braces are interpreted as escaped braces, and
both are converted to '{x}' in the final printed result.
In case 2, the format string is an f string. The substring is still {{x}}. The
first instance of {{x}} is found in the literal portion of the format string and
the double braces are interpreted as escaped braces. It expands to {x} like in
the first case. However, the second instance is found in the format spec, and
this case the outer braces are stripped off and what is left over is treated as
a Python expression. Here {x} is treated as a set literal containing one value,
x. Since x is 3, the value of int is {3}.
Case 3 confirms the interpretation of case 2 by simply replacing {x} with an
alternate way of specifying a set literal that contains a single value. In this
case there are no double braces and so both instances are treated the same, both
expand to {3}.
So the format method supports escaped braces in both the literal part of the
format string and the format spec. f-strings supports escaped braces in the
literal part of the format string, but in the format spec the outer level of
braces are stripped off and what remains is interpreted as a Python expression.
Is there some benefit to this difference?
-Ken
More information about the Python-ideas
mailing list