On Sat, May 19, 2018 at 07:06:41AM -0400, Eric V. Smith wrote: > On 5/19/2018 1:56 AM, Ken Kundert wrote: > >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? > > Is the difference you're seeing just in how f-strings and > str.format() differ in evaluating expressions? str.format() isn't > evaluating "int={x}", which makes sense to me. It never evaluates > expressions, by design, it just treats strings as literals. If it > did evaluate expressions, there's too great a chance of code being > evaluated from user-defined strings. > > Eric
Eric, My example does highlight the fact that f-strings do evaluate the embedded expressions while str.format() does not, but that is not the point I was trying to make. The substring 'int={{x}}' has two possible interpretations, it is either a string that contains escaped braces and when the escaping is processed becomes 'int={x}', or the outer braces signal an embedded expression, the expression being {x}, a set literal, and when interpolated the substring becomes 'int={3}'. My point was that str.format() uses the first interpretation for both ext and int, but f-strings use the first interpretation for ext and the second interpretation for int. Using the second interpretation for int in the f-string seems inconsistent. Specifically, int and ext are interpreted differently in the f-string, and int is interpreted differently by str.format() and the f-string. This difference does not seem to provide any benefit, so why does it exist? In other words, why aren't the escaped braces supported in the format_spec of f-strings? -Ken _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/