[Python-ideas] String interpolation for all literal strings
Eric V. Smith
eric at trueblade.com
Fri Aug 7 15:55:23 CEST 2015
On 08/07/2015 08:12 AM, Eric V. Smith wrote:
> On 8/7/2015 7:52 AM, Eric V. Smith wrote:
>> So (reverting to Python syntax, with the f-string syntax), in addition
>> to converting directly to a string, there's a way to go from:
>>
>> f'abc{expr1:spec1}def{expr2:spec2}ghi'
>>
>> to:
>>
>> ('abc{0:spec1}def{1:spec2}ghi', (value-of-expr1, value-of-expr2))
>>
>> The general idea is that you now have access to an i18n-able string, and
>> the values of the embedded expressions as they were evaluated "in situ"
>> where the f-string literal was present in the source code.
>> Y
>> ou can imagine the f-string above evaluating to a call to:
>>
>> __interpolate__('abc{0:spec1}def{1:spec2}ghi', (value-of-expr1,
>> value-of-expr2))
>>
>> The default implementation of __interpolate__ would be:
>>
>> def __interpolate__(fmt_str, values):
>> return fmt_str.format(*values)
>
> I should add that it's unfortunate that this builds a string for
> str.format() to use. The f-string ast generator goes through a lot of
> hassle to parse the f-string and extract the parts. For it to then build
> another string that str.format would have to immediately parse again
> seems like a waste.
>
> My current implementation of f-strings would take the original f-string
> above and convert it to:
>
> ''.join(['abc', expr1.__format__('spec1'), 'def',
> expr2.__format__(spec2), 'ghi'])
>
> Which avoids re-parsing anything: it's just normal function calls.
> Making __interpolate__ take a tuple of literals and a tuple of (value,
> fmt_str) tuples seems like giant hassle to internationalize, but it
> would be more efficient in the normal case.
If we do implement __interpolate__ as something like we're describing
here, it again brings up the question of concatenating adjacent strings
and f-strings. When I'm just calling expr.__format__ and joining the
results, you can't tell if I'm turning:
f'{a}' ':' f'{b}'
into multiple calls to join or not. But if we used __interpolate__, it
would make a difference if I called:
__interpolate__('{0}:{1}', (a, b))
or
''.join([__interpolate__('{0}', (a,)), ':', __interpolate('{0}', (b,))])
Eric.
More information about the Python-ideas
mailing list