[Python-ideas] Briefer string format

Eric V. Smith eric at trueblade.com
Mon Jul 20 21:52:12 CEST 2015


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".

> Not sure what you mean by "implicit merging" -- if you mean literal
> concatenation (e.g. 'foo' "bar" == 'foobar') then I think it should be
> allowed, just like we support mixing quotes and r''.

If I understand it, I think the concern is:

f'{a}{b}' 'foo{}' f'{c}{d}'

would need to become:
f'{a}{b}foo{{}}{c}{d}'

So you have to escape the braces in non-f-strings when merging strings
and any of them are f-strings, and make the result an f-string. But I
think that's the only complication.



More information about the Python-ideas mailing list