Cookbook - multireplace

Paul D. Lusk plusk at radford.edu
Thu Sep 19 20:45:10 EDT 2002


This is more an exercise in sub-classing a dict than a speed optimization.
It may not even be a speed optimization, since I didn't time it.


# Original algorithm by Xavier Defrang.
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
# and modified by alane at sourceforge.net
# This implementation by plusk at radford.edu

import re
 
class NotImplemented(Exception):
     pass
 
class textsub(dict):
    __slots__ = ('pat','regex','flags')
    def __init__(self, *ds):
        self.pat = None
        self.regex = None
        self.flags = None
        dict.__init__(self)
        for d in ds:
            self.update( d )
    def popitem(self):
        """popitem doesn't make sense for this class"""
        raise NotImplemented
    def setdefault(self,key,default):
#       print 'set default 1 %s %s' % (key, default)
        new = not dict(self).has_key(key)
        val = dict(self).get(key,default)
#       print 'set default 2 %s %s %s' % (key,default, val)
        if new:
            dict.__setitem__(self,key,default)
            self.compile()
        return val
    def update(self,newdict):
        dict.update(self,newdict)
        self.compile()
    def __setitem__(self,key,val):
        new = not dict(self).has_key(key)
        dict.__setitem__(self,key,val)
        if new:
            self.compile()
    def __delitem__(self,key):
        dict.__delitem__(self,key)
        self.compile()
    def compile(self):
#        print 'compile called'
        if dict(self) and len(dict(self)) > 0:
            tmp = "(%s)" % "|".join(map(re.escape,
                                        dict(self).keys()))
            if self.pat != tmp:
                self.pat = tmp
                if self.flags:
                    self.regex = re.compile(self.pat,self.flags)
                else:
                    self.regex = re.compile(self.pat)
                    
    # not called from outside, but is needed by
    # the sub below
    #  self.regex.sub(self,s) is regex.sub(func=self.__call__,s)
    def __call__(self, match):
        return dict(self)[match.group()]

    def sub(self, s):
        if len(dict(self)) == 0:
            return s
        return self.regex.sub(self, s)


if __name__ == "__main__": 
  text = "As you know, Bob, Larry Wall is the creator of Perl"
 
  adict = {
    "Larry Wall" : "Guido van Rossum",
    "creator" : "Benevolent Dictator for Life",
    "Perl" : "Python"
  } 
  print 'start'
  xlat = textsub(adict)
  print 'Fred for Bob'
  xlat["Bob"] = "Fred"
  print 'set default is'
  xlat.setdefault('is','really is')
  print xlat.sub(text)
  print """set default Bob, xlat['Bob'] is 'Fred'"""
  print xlat.setdefault('Bob','Jay')
  print xlat.sub(text)
  print """del xlat['Bob'], setdefault"""
  del xlat['Bob']
  print xlat.setdefault('Bob','Jay')
  print xlat.sub(text)
  print 'del creator'
  del xlat["creator"]
  print xlat.sub(text)
  print 'popitem'
  try:
      dummy1,dummy2 = xlat.popitem()
  except NotImplemented:
      print 'popitem not implemented'
  else:
      print 'oops'
  print 'clear'
  xlat.clear()
  print xlat.sub(text)




More information about the Python-list mailing list