Nested string substitutions

Mike Meyer mwm at mired.org
Sun Dec 29 21:17:35 EST 2002


[Apologies for digging out an old thread, but I spent the holiday with
my sons...]

holger krekel <pyth at devel.trillke.net> writes:
> Lulu of the Lotus-Eaters wrote:
> > |def expand(d):
> > |    while filter(lambda (n, v): d.__setitem__(n,
> > |        reduce(lambda x,k: x.replace(k, d[k]), d, v)
> > |    ) or v!=d[n], d.items()): pass
> > Wow!  Who ever said Perl was hard to read :-).  How long did that take
> > to think of, Holger?
> I produced a *readable* versions in 1-2 hours.  Using all the ideas
> from these versions the above snippet took around 20 minutes.  Maybe
> i mistake your original mail (where you mentioned one or two lines). 

That use of reduce is *very* cool. I think I missed something in the
docs, as I didn't realize dictionaries would turn into a sequence of
their keys.

> class subst_dict(dict):
>     def __call__(self, string, key=None):
>         """replace occurences of 'key' in 'string' with dict-value.
> 
>            for a None key all keys of the dict are applied
>            sequentially. If a key is not in the dict the
>            string is returned unmodified.
>         """
>         if key is None:
>             return reduce(self, self, string)
>         newstring = string.replace(key, self.get(key,key))
>         if newstring != string:
>             return self(newstring)
>         return newstring

Making it an ancester of the dict class feels very pythonic. The tail
recursion doesn't. Might I suggest:

   def __call__(self, string):
      previous = ""
      while previous != string:
         previous = string
         string = reduce(lambda x, k: x.replace(k, self[k]), self, string)

You probably went through this in your conversion. I find that once I
got my head around the reduce, having the string replacement in an
embedded lambda is easier to understand than having __call__ serve
double duty. That this also allows you to turn the tail recursion back
into a while loop is another boon to readability.

If you really want to keep the string with key replacment
functionality, it could be done as a separate method, and then that
method used in the reduce call.

        <mike
-- 
Mike Meyer <mwm at mired.org>			http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.



More information about the Python-list mailing list