[Python-3000] features i'd like [Python 3000?] ... #4: interpolated strings ala perl

Nick Coghlan ncoghlan at gmail.com
Mon Dec 4 13:13:58 CET 2006


Ben Wing wrote:
 > i see in PEP 3101 that there's some work going on to fix up the string
 > formatting capabilities of python.  it looks good to me but it still
 > doesn't really address the lack of a simple interpolated string
 > mechanism, as in perl or ruby.  i find myself constantly writing stuff like
 >
 > text="Family: %s" % self.name
 >
 > maybe_errout("%s, line %s: %s\n" % (title, lineno, errstr))
 >
 >     def __str__(self):
 >         return "CCGFeatval(%s, parents=%s, licensing=%s)" % (
 >             (self.name, self.parents, self.licensing))
 >
 > and lots of similar examples that are just crying out for perl-style
 > variable interpolation.  the proposals in PEP 3101 don't help much;

Have another look at PEP 3101. It already allows your examples to be written 
as follows:

  text = "Family: {0.name}".format(self)

  maybe_errout("{title}, line {lineno}: {errstr}\n".format(**locals()))

  return ("CCGFeatval({0.name}, "
          "parents={0.parents}, "
          "licensing={0.licensing})").format(self)

That said, it's conceivable that a separate function could be written that 
pokes around in the caller's locals instead of accepting a namespace argument:

  text = interp("Family: {self.name}")

  maybe_errout(interp("{title}, line {lineno}: {errstr}\n"))

  return interp(("CCGFeatval({self.name}, "
                 "parents={self.parents}, "
                 "licensing={self.licensing})"))

I'm not entirely averse to that idea, even though poking around in the frame 
stack is always somewhat dubious. I don't recall it coming up directly in 
previous discussions (certainly PEP 3101 doesn't say anything that explicitly 
rejects the concept).

OTOH, given a string formatting mechanism that accepts names and a mapping 
(like both %-formatting and PEP 3101), it's pretty easy to write your own 
implicit interpolation function:

 >>> def interp(fmt):
...     caller = sys._getframe(1)
...     return fmt % caller.f_locals
...
 >>> x = 1
 >>> interp("%(x)0.2f")
'1.00'

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
---------------------------------------------------------------
             http://www.boredomandlaziness.org


More information about the Python-3000 mailing list