if or elif either true then do something
Question:
this is just for academic interest. I encounter the following situation a lot.
either_true = False
if x:
...do something1
either_true = True
elif y:
...do something2
either_true = True
if either_true:
..do something3
is there any pythonic way of doing it, or in general better programming way of doing it.
Basically do something3 executes only if or elif is true.
Answers:
I would handle this by using nested if statements i.e.
if x or y:
if x:
...do something1
elif y:
...do something2
...do something3
As some comments have pointed out, the best solution will depend on what x & y are. If easy readability / concise code is your goal then this or other answers given should be fine. If however x & y were expensive function calls then it would be better to do something more like what you have done to avoid calling the function twice.
if x or y:
dosomethig1() if x else dosomething2()
dosomething3()
Of course, this does evaluate x.__nonzero__
twice. Usually that’s not a big deal, but if it is expensive, you can always evaluate that upfront and save it to a temporary variable.
You could wrap some of it in a function:
def do_stuff():
if x:
...do something1
return True
elif y:
...do something2
return True
else:
return False
if do_stuff():
..do something3
Or all of it in a function:
def do_stuff()
if x:
...do something1
elif y:
...do something2
else:
return
..do something3
You could also omit the either_true
flag completely if doSomething3
is a single line of code (e.g. a function call):
if x:
..do something 1
..do something 3
elif y:
..do something 2
..do something 3
It maintains the nice property of evaluating x
and y
at most once (and y
won’t be evaluated if x
is true).
either_true = x or y
if x:
...do something1
elif y:
...do something2
if either_true:
..do something3
In the spirit of offering a completely different solution to those already proposed, you could set up a list structured dictionaries which allows you to set up multiple cases bound to your predefined “somethings”
cases = [
{'condition' : x, 'action' : something1},
{'condition' : not x and y, 'action' : something2},
{'condition' : x or y, 'action' : something3},
]
for c in cases:
if c['condition']: c['action']
I actually really like this method (and I’ve only just discovered it when trying to come up with a unique answer to this question, thanks!) – it’s really obvious which case is bound to which action, and it’s easy to add several more cases without adding any more if/else statements.
Your code is almost optimal, as far as code repetition and evaluation are concerned. The only thing I can think of to avoid repetition would be:
# be optimistic!
either_true = True
if x:
do_something1
elif y:
do_something2
else:
either_true = False
if either_true:
do_something3
This removes one assignment, although the total number of lines doesn’t change.
The advantage is that this works with n
conditions, without adding any other assignment, while your current solution requires an either_true = True
for every condition.
In my opinion they have about the same degree of readability, but the above code will be better with more conditions.
Also there’s no “pythonic” way other then a readable solution that avoids code repetition and is optimal in terms of efficiency, and I don’t know of any kind of “better programming” to achieve the same result.
I would wrap the ..do somethings in functions and write one if-elif:
def do_x():
.. do something 1
.. do something 3
def do_y():
.. do something 2
.. do something 3
if x:
do_x()
elif y:
do_y()
This is nice if the .. do somethings involve a lot of stuff.
For all of these suggestions and any others you come up with, note that if x
and y
are expensive expressions:
if askTheServer() or readTheOneGigabyteConfigFile():
...
you can assign the values these expressions return to quick-to-evaluate variables first:
x = askTheServer()
y = readTheOneGigabyteConfigFile()
if x or y :
...
if do something is quite short, like do(1), do(2) or something like that, you can just do it like this:
(x and (do(1), x) or y and (do(2), y)) and do(3)
this is just for academic interest. I encounter the following situation a lot.
either_true = False
if x:
...do something1
either_true = True
elif y:
...do something2
either_true = True
if either_true:
..do something3
is there any pythonic way of doing it, or in general better programming way of doing it.
Basically do something3 executes only if or elif is true.
I would handle this by using nested if statements i.e.
if x or y:
if x:
...do something1
elif y:
...do something2
...do something3
As some comments have pointed out, the best solution will depend on what x & y are. If easy readability / concise code is your goal then this or other answers given should be fine. If however x & y were expensive function calls then it would be better to do something more like what you have done to avoid calling the function twice.
if x or y:
dosomethig1() if x else dosomething2()
dosomething3()
Of course, this does evaluate x.__nonzero__
twice. Usually that’s not a big deal, but if it is expensive, you can always evaluate that upfront and save it to a temporary variable.
You could wrap some of it in a function:
def do_stuff():
if x:
...do something1
return True
elif y:
...do something2
return True
else:
return False
if do_stuff():
..do something3
Or all of it in a function:
def do_stuff()
if x:
...do something1
elif y:
...do something2
else:
return
..do something3
You could also omit the either_true
flag completely if doSomething3
is a single line of code (e.g. a function call):
if x:
..do something 1
..do something 3
elif y:
..do something 2
..do something 3
It maintains the nice property of evaluating x
and y
at most once (and y
won’t be evaluated if x
is true).
either_true = x or y
if x:
...do something1
elif y:
...do something2
if either_true:
..do something3
In the spirit of offering a completely different solution to those already proposed, you could set up a list structured dictionaries which allows you to set up multiple cases bound to your predefined “somethings”
cases = [
{'condition' : x, 'action' : something1},
{'condition' : not x and y, 'action' : something2},
{'condition' : x or y, 'action' : something3},
]
for c in cases:
if c['condition']: c['action']
I actually really like this method (and I’ve only just discovered it when trying to come up with a unique answer to this question, thanks!) – it’s really obvious which case is bound to which action, and it’s easy to add several more cases without adding any more if/else statements.
Your code is almost optimal, as far as code repetition and evaluation are concerned. The only thing I can think of to avoid repetition would be:
# be optimistic!
either_true = True
if x:
do_something1
elif y:
do_something2
else:
either_true = False
if either_true:
do_something3
This removes one assignment, although the total number of lines doesn’t change.
The advantage is that this works with n
conditions, without adding any other assignment, while your current solution requires an either_true = True
for every condition.
In my opinion they have about the same degree of readability, but the above code will be better with more conditions.
Also there’s no “pythonic” way other then a readable solution that avoids code repetition and is optimal in terms of efficiency, and I don’t know of any kind of “better programming” to achieve the same result.
I would wrap the ..do somethings in functions and write one if-elif:
def do_x():
.. do something 1
.. do something 3
def do_y():
.. do something 2
.. do something 3
if x:
do_x()
elif y:
do_y()
This is nice if the .. do somethings involve a lot of stuff.
For all of these suggestions and any others you come up with, note that if x
and y
are expensive expressions:
if askTheServer() or readTheOneGigabyteConfigFile():
...
you can assign the values these expressions return to quick-to-evaluate variables first:
x = askTheServer()
y = readTheOneGigabyteConfigFile()
if x or y :
...
if do something is quite short, like do(1), do(2) or something like that, you can just do it like this:
(x and (do(1), x) or y and (do(2), y)) and do(3)