best way to do a series of regexp checks with groups

Steven Bethard steven.bethard at gmail.com
Mon Jan 24 04:04:31 EST 2005


Alex Martelli wrote:
> class ReWithMemory(object):
>     def search(self, are, aline):
>         self.mo = re.search(are, aline)
>         return self.mo
>     def group(self, n):
>         return self.mo.group(n)
> 
> m = ReWithMemory()
> 
> if m.search(r'add (\d+) (\d+)', line):
>     do_add(m.group(1), m.group(2))
> elif m.search(r'mult (\d+) (\d+)', line):
>     do_mult(m.group(1), m.group(2))
> elif m.search(r'help (\w+)', line):
>     show_help(m.group(1))
> 
> Demeter's Law suggests that the 'm.value.group' accesses in your
> approach are better handled by having m delegate to its `value'; and the
> repeated m.set(re.search( ... seem to be a slight code smell, violating
> "once and only once", which suggests merging into a single `set' method.
> Your approach is more general, of course.

I get a bit uneasy from the repeated calls to m.group...  If I was going 
to build a class around the re, I think I might lean towards something like:

class ReWithMemory(object):
     def search(self, are, aline):
         self.mo = re.search(are, aline)
         return self.mo
     def groups(self, *indices):
         return [self.mo.group(i) for i in indices]

m = ReWithMemory()

if m.search(r'add (\d+) (\d+)', line):
     do_add(*m.groups(1, 2))
elif m.search(r'mult (\d+) (\d+)', line):
     do_mult(*m.groups(1, 2))
elif m.search(r'help (\w+)', line):
     show_help(*m.groups(1))

Of course, this is even less general-purpose than yours...

(And if I saw myself using this much regex code, I'd probably reconsider 
my strategy anyway.) ;)

Steve



More information about the Python-list mailing list