Nested string substitutions

holger krekel pyth at devel.trillke.net
Sat Dec 21 07:30:57 EST 2002


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). 

FWIW, if i wanted readability and general usability i'd go for 
making subst_dict a callable object providing substition for
a string.  And provide a separate (in place) expand method. 

class subst_dict(dict):
    def __init__(self, *args, **kwargs):
        """convenience: keyword arguments go into dict """
        super(subst_dict, self).__init__(*args)
        self.update(kwargs)

    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

    def expand(self):
        """expand all dictionary keys in place. """
        for key,value in self.items():
            self[key] = self(value)

usage:

>>> d = subst_dict(a='1', b='2', c='ab')
>>> d('c')  # doesn't change dict
'12'
>>> d['12']='77'
>>> d('c')  
'77'
>>> d
{'a': '1', '12': '77', 'c': 'ab', 'b': '2'}
>>> d.expand()
>>> d
{'a': '1', '12': '77', 'c': '77', 'b': '2'}
>>>

This way you can also pass a subst_dict instance around 
and do stuff like

    subst_strings = map(d, strings)

expand() merely becomes an optimization. 

cheers,

    holger




More information about the Python-list mailing list