[Python-ideas] Draft PEP on string interpolation

Guido van Rossum guido at python.org
Sun Aug 23 06:09:31 CEST 2015


On Sat, Aug 22, 2015 at 6:37 PM, Nick Coghlan <ncoghlan at gmail.com> wrote:

> On 23 August 2015 at 08:50, Guido van Rossum <guido at python.org> wrote:
> > OTOH this topic is rich enough that I have no problem spending a few more
> > PEP numbers on it. If Mike asks for a PEP number I am not going to
> withhold
> > it.
>
> Aye, agreed - at the very least, we want to preserve his survey of
> interpolation in other languages, as I found that to be an incredibly
> valuable contribution.
>

For that he should just update the Wikipedia page on the topic.Or maybe
write the PEP, and then update Wikipedia, using the PEP as the [needed
citation]. :-)


> >> > 2.  Have I died and gone to Perl?
> >>
> >> That's my question in relation to PEP 498 - it seems to introduce lots
> >> of line noise for people to learn to read for little to no benefit (my
> >> perspective is heavily influenced by the fact that most of the code I
> >> write myself these days consists of network API calls + logging
> >> messages + UI template rendering, with only very occasional direct
> >> calls to str.format that use anything more complicated than "{}" or
> >> "{!r}" as the substitution field).
> >>
> >> As a result, I'd be a lot more comfortable with PEP 498 if it had more
> >> examples of potential practical use cases, akin to the examples
> >> section from PEP 343 for context managers.
> >
> > Since you accept "!r", you must be asking about the motivation for
> including
> > ":spec", right?
>
> Sorry, I wasn't clear - PEP 501 also retains the field formatting
> capabilities, and is hence strictly "noisier" than PEP 498 (especially
> the ! prefix version of the syntax). It's just that it solves enough
> *other* problems for it to seem worth the cost to me.


Wow. "PEP 498 seems to introduce a lot of line noise" was a rather broken
way to say that...


> When the benefit
> is "str.format is prettier, all other forms of interpolation remain
> repetitively verbose",


Who says that, and what does it mean?


> it seems a very invasive change just to
> replace:
>
>     print("Chopped {} onions in {:.3f} seconds.".format(n, t1-t0))
>
> with:
>
>     print(f"Chopped {n} onions in {t1-t0:.3f} seconds.")
>

But only people who are politically correct about it use str.format().
Everyone else (and the logging module :-) still uses %.


> >> While the second draft of PEP 501 is even more line-noisy than PEP 498
> >> due to the use of both "!" and "$", it at least generalises the
> >> underlying semantics of compiler-assisted interpolation to apply to
> >> additional use cases like logging, i18n (including compatibility
> >> with Mozilla's l20n syntax), safe SQL interpolation, safe shell
> >> command interpolation, HTML template rendering, etc.
> >
> >
> > That's perhaps a bit *too* ambitious. The claim of "safety" for PEP 498
> is
> > simple -- it does not provide a way for a dynamically generated string to
> > access values in the current scope (and it does this by not supporting
> > dynamically generated strings). For most domains you mention, safety is
> much
> > more complex, and in fact mostly orthogonal -- code injection attacks
> rely
> > on the value of the interpolated variables, so PEP 498's "safety" does
> not
> > help at all.
>
> Right, but that's where I came to the conclusion that the lack of
> arbitrary interpolation support ends up making PEP 498 actively
> dangerous, as string interpolation based substitution ends up being so
> much prettier than doing things right. Compare:
>
>     os.system(f"echo {filename}")
>     subprocess.call(f"echo {filename}")
>     subprocess.call(["echo", filename])
>
> Even in that simple case, the two unsafe approaches are much nicer to
> read, and as the command line gets more complex, the safe version gets
> harder and harder to read relative to the unsafe ones.
>

That reasoning is perverse, and feels disingenuous.


> With the latest PEP 501 draft (which switched the proposed syntax and
> semantics to behave more like a traditional binary operator), we could
> make invoking a subprocess *safely* look like:
>
>     subprocess.call $"echo $filename"
>

Which reminds me of your one-time attempts to make call parentheses
optional, so we could have print be a function and yet be able to write

  print x, y


> However, I'm now coming full circle back to the idea of making this a
> string prefix, so that would instead look like:
>
>     subprocess.call($"echo $filename")
>
> The trick would be to make interpolation lazy *by default* (preserving
> the triple of the raw template string, the parsed fields, and the
> expression values), and put the default rendering in the resulting
> object's *__str__* method.
>

That's a clever idea. But I expect it will make interpolation much less
convenient, because every recipient will have to call str(). The elegance
of PEP 498 is that the recipient doesn't have to do or know anything
special, because the result is *just* a string object.


> That description is probably as clear as mud, though, so back to the
> PEP I go! :)
>

I recommend taking a break first. Or maybe sample the recent activity in
datetime-sig instead. :-)

-- 
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20150822/191dbf75/attachment-0001.html>


More information about the Python-ideas mailing list