[Python-ideas] Draft PEP on string interpolation

Eric V. Smith eric at trueblade.com
Mon Aug 24 17:55:35 CEST 2015


I should have added: this is for i-strings that look like PEP 498's
f-strings. I'm not trying to jump to conclusions about the syntax: I'm
just trying to reuse some code, and making i-strings and f-strings look
like str.format strings allows me to reuse lots of infrastructure (as I
hope can be seen from this example).

For the final version, we can choose whatever syntax makes sense. I
would argue for i"Value={value}" (same for f-strings), but if we decide
to make it something else, I'll live with the decision.

Eric.

On 08/24/2015 11:14 AM, Eric V. Smith wrote:
> On 08/23/2015 09:13 PM, Guido van Rossum wrote:
>> But for i-strings, I think it would be good if we could gather more
>> actual experience using them. Every potential use case brought up for
>> these so far (translation, html/shell/sql quoting) feels like there's a
>> lot of work needing to be done to see if the idea is actually viable
>> there. It would be a shame if we added all the (considerable!) machinery
>> for i-strings and all we got was yet another way to do it
>> (https://xkcd.com/927/), without killing at least one competing approach
>> (similar to the way .format() has failed to replace %).
>>
>> It's tough to envision how we could gather more experience with
>> i-strings *without* building them into the language, but I'm really
>> hesitant to add them without more experience. (This is the "new on the
>> job market" paradox. :-) Maybe they could be emulated using a function
>> call that uses sys._getframe() under the covers? Or maybe it's possible
>> to cook up an experiment using other syntax hooks? E.g. the coding hack
>> used in pyxl (https://github.com/dropbox/pyxl).[1]
> 
> 
> I hope you don't mind that I borrowed the keys to the time machine. I'm
> using the implementation of _string.formatter_parser() that I added for
> implementing string.Formatter:
> 
> ---8<---------------------------------------------
> import sys
> import _string
> 
> class i:
>     def __init__(self, s):
>         self.s = s
>         locals = sys._getframe(1).f_locals
>         globals = sys._getframe(1).f_globals
>         self.values = {}
>         # evaluate the expressions
>         for literal, expr, format_spec, conversion in \
>                 _string.formatter_parser(self.s):
>             if expr:
>                 value = eval(expr, locals, globals)
>                 self.values[expr] = value
> 
>     def __str__(self):
>         result = []
>         for literal, expr, format_spec, conversion in \
>                 _string.formatter_parser(self.s):
>             result.append(literal)
>             if expr:
>                 value = self.values[expr]
>                 result.append(value.__format__(format_spec))
>         return ''.join(result)
> ---8<---------------------------------------------
> 
> So now, instead of i"x={x}", we say i("x={x}").
> 
> Let's use it with str:
> 
>>>> x = i('Version in caps {sys.version[0:7].upper()}')
>>>> x
> <__main__.i object at 0x7f1653311e90>
>>>> str(x)
> 'Version in caps 3.6.0A0'
> 
> 
> Cool. Now let's whip up a simple i18n example:
> 
>>>> def gettext(s):
> ...     # Our complicated string lookup
> ...     if s == 'My name is {name}, my dog is {dog}':
> ...         return 'Mi pero es {dog}, y mi nombre es {name}'
> ...     return s
> ...
>>>> def _(istring):
> ...     result = []
> ...     # do the gettext lookup
> ...     s = gettext(istring.s)
> ...     # use the values from our original istring,
> ...     #  but the literals and ordering from our
> ...     #  looked-up string
> ...     for literal, expr, format_spec, conversion in \
> ...             _string.formatter_parser(s):
> ...         result.append(literal)
> ...         if expr is not None:
> ...             result.append(istring.values[expr])
> ...     return ''.join(result)
> ...
>>>> name = 'Eric'
>>>> dog = 'Misty'
>>>> x = i('My name is {name}, my dog is {dog}')
>>>> str(x)
> 'My name is Eric, my dog is Misty'
>>>> _(x)
> 'Mi pero es Misty, y mi nombre es Eric'
>>>>
> 
> That should be enough to play with i-strings in logging, sql, xml, etc.
> 
> Several things should be addressed: hiding the call to
> _string.formatter_parse inside the 'i' class, for example. And of course
> don't use sys._getframe. But the ideas are all there.
> 
> I can't swear that _string.formatter_parser will parse all known
> expressions, since that's not what it was designed to do. It will likely
> fail with expressions that contain strings and braces, for example. I
> haven't really checked. But hey, what do you want for free?
> 
> With a slight tweak, this code even works with 2.7: replace
> "_string.formatter_parser" with "str._formatter_parser". Unfortunately,
> 2.7 will then only support very simple expressions. Oh, well.
> 
> Enjoy!
> 
> Eric.
> 
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
> 



More information about the Python-ideas mailing list