assignment expression peeve

Peter Otten __peter__ at web.de
Wed Oct 15 06:08:34 EDT 2003


Paul Rubin wrote:

> It gets annoying when there are 4 different regexps that the line
> might match, and I want to do something different depending on which
> one matches.  That's not that uncommon a text scanning situation.
> With assignment expressions, it's a very natural if/elif chain:
> 
>    for line in file:
>      if g := re.match(pat1, line):
>         croggle(g.group(1), 17)
>      elif g := re.match(pat2, line):
>         x = mugwump(g.group(3))
>         y = wumpus(g.group(2))
>         return defenestrate(x, y+3)
>      elif g := re.match(pat3, line):
>         # do something completely different with groups of g
>      elif g := re.match(pat4, line):
>         # more of the same
> 
> Without assigment expressions, it gets unspeakably ugly.  You have to
> use a deeply nested if/else if sequence where you match the regexp and
> test the result on 2 separate lines at each branch, or reorganize the
> code to use some kind of dispatch table (good if there's a lot more
> than 4 regexps, but overkill for just 4), or whatever.  I ended up
> creating a special class instance just to match a regexp and remember
> the result, so I could write in the if/elif style.
> 
> This kind of regexp matching is a common pattern and I keep wanting
> assignment expressions whenever I code it, and end up crocking up some
> silly workaround.

Here's yet another "silly workaround" that attacks the inline assignment
problem in the most general form I can think of. Instead of g := expr, use
g(expr). The overhead is an additional get() method call when accessing the
value. 
Of course you could delegate attribute access as Alex Martelli did, but this
reminds me too much of C++ STL's auto_ptr :-)

class Assign(object):
    def __call__(self, value):
        self.value = value
        return value
    def get(self):
        return self.value

#sample usage
g = Assign()
for line in file:
    if g(re.match(pat1, line)):
        croggle(g.get().group(1), 17)
    elif g(re.match(pat2, line)):
        x = mugwump(g.get().group(3))
        y = wumpus(g.get().group(2))
        return defenestrate(x, y+3)
    elif g(re.match(pat3, line)):
        # do something completely different with groups of g
    elif g(re.match(pat4, line)):
        # more of the same

Peter




More information about the Python-list mailing list