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