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.

Asked By: Shh

||

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.

Answered By: ChrisProsser
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.

Answered By: mgilson

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
Answered By: Eric

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).

Answered By: Frerich Raabe
either_true = x or y
if x:
  ...do something1
elif y:
  ...do something2
if either_true:
  ..do something3
Answered By: petabyte

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.

Answered By: Quentin Donnellan

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.

Answered By: Bakuriu

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.

Answered By: celeritas

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 :
   ...
Answered By: Kevin

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)
Answered By: nicky_zs
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.