[Python-Dev] PEP 498 (interpolated f-string) tweak

Eric V. Smith eric at trueblade.com
Sat Sep 19 21:36:40 CEST 2015


On 9/19/2015 3:22 PM, Serhiy Storchaka wrote:
> On 19.09.15 14:03, Eric V. Smith wrote:
>> While finishing up the implementation of PEP 498, I realized that the
>> PEP has an error. It says that this code:
>>
>> f'abc{expr1:spec1}{expr2!r:spec2}def{expr3:!s}ghi'
>>
>> Is equivalent to:
>>
>> 'abc' + expr1.__format__(spec1) + repr(expr2).__format__(spec2) + 'def'
>> + str(expr3).__format__('') + 'ghi'
>>
>> But that's not correct. The right way to call __format__ is:
>>
>> type(expr1).__format__(expr1, spec1)
>>
>> That is, the lookup of __format__ is done on the type, not the instance.
>>
>> Instead of calling __format__, I've changed the code generator to call
>> format(expr1, spec1). As an optimization, I might add special opcodes to
>> deal with this and string concatenation, but that's for another day (if
>> ever).
> 
> Concatenating many strings is not efficient. More efficient way is to
> use string formatting. Why not translate f-string to
> 
>     'abc%s%sdef%sghi' % (format(expr1, spec1),
>                          format(repr(expr2), spec2), expr3)

As the PEP says, the expression with '+' is illustrative, not how it's
actually implemented. The implementation currently uses ''.join,
although I reserve the right to change it.

> or even to
> 
>     'abc{:spec1}{!r:spec2}def{!s}ghi'.format(expr1, expr2, expr3)

That's surprisingly difficult to get right. I've implemented the code at
least 3 different ways, and the current implementation seems the most
straightforward. I might add a special opcode to use a _PyUncode_Writer,
though.

Eric.


More information about the Python-Dev mailing list