[Python-Dev] PEP 292, Simpler String Substitutions

Donald Beaudry Donald Beaudry <donb@abinitio.com>
Wed, 19 Jun 2002 17:23:47 -0400

Guido van Rossum <guido@python.org> wrote,
> I think little would be lost if sub() always required a dict (or
> perhaps keyword args, although that feels like a YAGNI now).

Requiring the dict sounds about right to me.  But, now when you
consider that the sub() being discussed is litte more than

  import re

  def sub(s, **kws):
      return re.sub(r"\${\w+}", lambda m, d=kws: d[m.group(0)[2:-1]], s)

  print sub("this is ${my} way to ${sub}", my="Don's", sub="do it")

you just have to wonder what the fuss is really all about.  Ease of
use seems to be the issue.  Should this variant of sub() just be added
to the re module?  With such a friendly introduction, it might coax
new users into looking deeper into the power of re.

There seems to be another issue though: the default value for the
substitution dictionary and whether a KeyError or NameError should be
raised when a key doesnt exist.  Why not just define a new mapping
object, returned from a call to namespace() that behaves something
like this (bogus implementation):

  class namespace:
      def __getitem__(s, k):
          return eval(k)


  print sub("this is ${my} way to ${sub}", **namespace())

Should do the right thing.  The fun here is that the namespace()
mechanism would be available for further abuse.  I see no reason to
lock it up inside a string interpolation function.  Consideration
should even be given to allowing a frame index argument to be passed
to it.  So,

  def sub(s, **kws):
      if not kws:
          kws = namespace(-1)
      return re.sub(r"\${\w+}", lambda m, d=kws: d[m.group(0)[2:-1]], s)

would do the complete job.  But that might be too much like upvar ;)

Donald Beaudry                                     Ab Initio Software Corp.
                                                   201 Spring Street
donb@abinitio.com                                  Lexington, MA 02421
                          ...So much code...