if/elif chain with assignment expressions

Duncan Booth me at privacy.net
Mon Jul 12 11:25:05 EDT 2004


"Larry Bates" <lbates at swamisoft.com> wrote in news:RPudnSx-4L-GOW_dRVn-
uw at comcast.com:
> "Paul Rubin" <http://phr.cx@NOSPAM.invalid> wrote in message
> news:7xvfguflq1.fsf_-_ at ruckus.brouhaha.com...
>> Sometimes you want to compute an expression, then do something with
>> the value if it meets a certain criterion; otherwise, try a different
>> expression (and maybe different criterion) instead, etc.
> What about:
> 
> e_list=[{'condition': 'f(y) < 5', 'call': fred},
>         {'condition': 'f(y) < 7', 'call': ted},
>         {'condition': 'f(y) < 9', 'call': ned}]
> 
> for e in e_list:
>     if eval(e['condition']):
>         e['call'](y)
>         break

(I've moved the response to after the original text so that people can 
follow the thread)

It isn't generally a good idea to use eval when there are better options 
around. Your suggestion could equally well be written without the eval:
(Changed back to f, g, h as per original post)

e_list=[{'condition': lambda: f(y) < 5, 'call': fred},
        {'condition': lambda: g(y) < 7, 'call': ted},
        {'condition': lambda: h(y) < 9, 'call': ned}]

for e in e_list:
    if e['condition']():
        e['call'](y)
        break

Whilst I see your reason for using a dictionary, I would tend more towards 
a tuple for code like this:

def doit(y):
    e_list=[ (lambda: f(y) < 5, fred),
             (lambda: g(y) < 7, ted),
             (lambda: h(y) < 9, ned)]
    for (condition,action) in e_list:
        if condition():
            action(y)
            break

If the program contains multiple bits of code like this, you could 
naturally extract the for loop out into another function, whereupon this 
becomes:

def doit(y):
    do_first_true((lambda: f(y) < 5, fred),
             (lambda: g(y) < 7, ted),
             (lambda: h(y) < 9, ned))

def do_first_true(*branches):
    for (condition,action) in branches:
        if condition():
            action(y)
            break

which is definitely less messy than assignments in conditionals and allows 
for variations on the theme such as do_all_true.



More information about the Python-list mailing list