string interpolation for python

Chris Angelico rosuav at gmail.com
Mon Apr 2 18:38:13 EDT 2012


On Tue, Apr 3, 2012 at 4:56 AM, Steven D'Aprano
<steve+comp.lang.python at pearwood.info> wrote:
> On Tue, 03 Apr 2012 00:58:38 +1000, Chris Angelico wrote:
>
>> I can't find a way to use an argument more than once,
>> without switching to "dictionary mode" and using keys for everything.
>
> Ack.
>
> In this case, you can use format:
>
>>>> "Hello {0}, what's up with {1}? Hey, {0} I'm speaking to you!".format
> ('George', 'Melissa')
> "Hello George, what's up with Melissa? Hey, George I'm speaking to you!"

Yes, it's possible with that version but not with % formatting. (Is
your "Ack" short for "Acknowledgement", or is it an ejaculation of
disgust?)

On Tue, Apr 3, 2012 at 1:49 AM, Yingjie Lan <lanyjie at yahoo.com> wrote:
> Then we can have:
>>>> d"sin($x$) = $ sin(x):0.3f $"
> get translated to:
>>>> ''.format_join(["sin(%s",x,") = %0.3f", sin(x)])
> This seems to be at least as good in performance.

Or don't bother with the initial string, and simply pass everything as
arguments:

def yingjie_format(*args):
    it=iter(args)
    return ''.join(s%next(it,None) for s in it)
yingjie_format("sin(%s",x,") = %0.3f", sin(x))

Tested and working (Python 3.2 on Windows). Okay, the generator's a
bit cryptic, but you could do the same with a more explicit loop if
you prefer.

> Syntax highlighting: can be done more creatively.
> For dynamic strings, string parts are like normal
> strings, but the embedded expressions are like
> normal expressions :)

So if they're exactly like normal expressions, why not simply use
normal expressions?

>> sprintf("UPDATE tablename SET modified=now()%{,%s=:%[0]s%} WHERE
>> key=%d",array_of_field_names,primary_key_value)
>> --> "UPDATE tablename SET modified=now(),foo=:foo,bar=:bar,quux=:quux
>> WHERE key=1234"
>>
>> You're still paying for no complexity you aren't actually using.
>> It's clear and readable.
>
> You are really good at that. Maybe not everybody is as
> experience as you, and I suppose the learning curve is
> kind of hard to climb.

Yes, it takes some learning to use it. But that's true of everything,
no less of your magical string interpolation. My point is that simple
examples should be (and are, with printf formatting) simple, such that
you only get those more complicated format strings when you're
actually doing a complicated job (in that case, taking each element of
an array and using it twice - actually, it was taking the indices of a
mapping that would end up being passed to the DB query function, thus
providing values to the :foo :bar variables).

> Those expressions are embedded, you don't need eval()
> to have the result though. Are we on the same page?

I can see three implementation paths:

1) Language feature. It really *is* just an expression. There's no way
that a user can provide them, so there's actually no similarity to
eval. But this requires that Python itself handle things.

2) Precompiler. It *becomes* an expression. Again, perfectly safe,
although I don't know how useful this really is.

3) Functoin. As several have suggested, you could do some magic and
use d("this is a $dollar$ $interpolated$ string") to implement. For
this, you *will* need eval (or something like it).

>> Here's a recommendation: Write a parser for your notation that turns
>> it into executable Python code (that is, executable in Python 3.3
>> without any d"..." support).
>
> You mean a translator?

Yes. It translates your dollar-strings into something that's legal
Python 3.3 syntax - either calls to a function like I provided above,
or actual embedded expressions.

> The syntax is essential for compatibility.
> We must distinguish dynamic strings from common strings.
> They will live peacefully together.
> (escaping the '$' in normal strings breaks compatibility,
> and the consequence of forgetting to escape could be
> disastrous, so definitely not an option).
>
> May be d" is too tiny, $"..." is easier to pick out.

I don't like the use of symbols like that; can someone, glancing at
your code, tell whether $ is an operator, a name, or something else?
The original d is probably better for that.

ChrisA



More information about the Python-list mailing list