[Python-ideas] Draft PEP on string interpolation
Eric V. Smith
eric at trueblade.com
Mon Aug 24 17:14:53 CEST 2015
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.
More information about the Python-ideas
mailing list