[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