[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