[Python-ideas] Briefer string format

Eric V. Smith eric at trueblade.com
Mon Jul 20 22:20:03 CEST 2015


On 07/20/2015 03:52 PM, Eric V. Smith wrote:
> On 07/20/2015 03:22 PM, Guido van Rossum wrote:
> 
>>     > So the idea is that
>>     > f'x:{a.x} y:{y}'
>>     > would translate to bytecode that does:
>>     > 'x:{a.x} y:{y}'.format(a=a, y=y)
>>     >
>>     > Correct?
>>
>>     That's exactly what I had in mind, at least. Indexing is supported
>>     in format strings too, so f'{a[1]}' also becomes
>>     '{a[1]}'.format(a=a), but I don't think there are any other strange
>>     cases here. I would vote for f'{}' or f'{0}' to just be a SyntaxError.
>>
>>
>> +1 on that last sentence. But I prefer a slightly different way of
>> implementing (see my reply to Eric).
> 
> Right. And following up here to that email:
> 
>> I was more thinking of translating that specific example to
>>
>>     'x:{} y:{}'.format(a.x, y)
>>
>> which avoids some of the issues your example is trying to clarify.
> 
> That is better. The trick is converting the string "a.x" to the
> expression a.x, which should be easy enough at compile time.
> 
>> It would still probably be best to limit the syntax inside {} to exactly
>> what regular .format() supports, to avoid confusing users.
> 
> The expressions supported by .format() are limited to attribute access
> and "indexing". We just need to enforce that same restriction here.
> 
>> Though the consistency argument can be played both ways -- supporting
>> absolutely anything that is a valid expression would be more consistent
>> with other places where expressions occur. E.g. in principle we could
>> support operators and function calls here.
> 
> It would be easiest to not restrict the expressions, but then we'd have
> to maintain that restriction in two places.
> 
> And now that I think about it, it's somewhat more complex than just
> expanding the expression. In .format(), this:
> '{a[0]}{b[c]}'
> is evaluated roughly as
> format(a[0]) + format(b['c'])
> 
> So to be consistent with .format(), we have to fully parse at least the
> indexing out to see if it looks like a constant integer or a string.
> 
> So given that, I think we should just support what .format() allows,
> since it's really not quite as simple as "evaluate the expression inside
> the braces".

And thinking about it yet some more, I think the easiest and most
consistent thing to do would be to translate it like:

f'{a[0]}{b[c]}' == '{[0]}{[c]}'.format(a, b)

So:
f'api:{sys.api_version} {a} size{sys.maxsize}'

would become either:
f'api:{.api_version} {} size{.maxsize}'.format(sys, a, sys)
or
f'api:{0.api_version} {1} size{0.maxsize}'.format(sys, a)

The first one seems simpler. The second probably isn't worth the
micro-optimization, and it may even be a pessimization.

Eric.



More information about the Python-ideas mailing list