jack.py
jack.py

Reputation: 442

Is there an “elif” equivalent in for/else statements

In if/elif/else statements, elifs are checked if the if is false, and if both the if and elifs are false then the else is run.

For loops have something similar with the else keyword - if the loop doesn’t encounter a break, then the code inside else is run.

So, for loops have an else equivalent to if/elif/else statements. My question is however, is there an equivalent to elif.

I’m thinking that it would be something along the lines of:

I’m aware you can emulate this effect. Just as you can do this with if/else statements to emulate the elif:

if condition:
    do_something()
else:
    if another_condition:
        do_something_else()
    else:
        default()

you can do this with for loops:

for x in y:
    if condition:
        break
else:
    for n in m:
        if another_condition:
            break
    else:
        default()

While the above code is valid, like with if/else statements, it’s faily ugly and I was hoping to find a better alternative.

Upvotes: 0

Views: 218

Answers (4)

user2390182
user2390182

Reputation: 73460

While the for-loop syntax doesn't allow this (as shown by @Carcigenicate), you can keep nesting levels down by using a try-else:

try:
    for x in y:
        if z:
            raise SomeException
    for m in n:
        if o:
            raise SomeException
except SomeException:
    pass
else:
    default()

A cleaner way, however, might wrap the loops in functions:

# these can be more complex non-anonymous functions
f1 = lambda: any(1 for x in y if z)
f2 = lambda: any(1 for m in n if o)
f3 = ...

if not any(f() for f in (f1, f2, f3)):
    default()

Upvotes: 1

mapf
mapf

Reputation: 2058

What if you make the variable that determins whether you should continue global? Since if any of the conditions are met, you don't want to continue with any of the following loops this should work:



def do_something():
    for i in range(3):
        condition = i < 3
        if not condition:
            return False

    return True


def do_something_else():
    for i in range(3):
        condition = i < 2
        if not condition:
            return False

    return True


condition_met = True
if condition_met:
    print('we start here')
    condition_met = do_something()
if condition_met:
    print('and should get here')
    condition_met = do_something_else()
if condition_met:
    print('but not here')

It may not be amazing, but at least it's not nested, and sort of looks like the syntax you're looking for.

You could also use a while loop:

operations = [do_something, do_something_else] 
i = 0
while condition_met and i < len(operations):
    condition_met = operations[i]() 

Upvotes: 1

Michał Kandybowicz
Michał Kandybowicz

Reputation: 1

I'm not sure, but maybe while will be ok for you

i = 0
while i < 10:
  if condition:
    break
  i += 1

Upvotes: -3

Carcigenicate
Carcigenicate

Reputation: 45740

No. If you look at the grammar of the for statement:

for_stmt:
    | 'for' star_targets 'in' ~ star_expressions ':' [TYPE_COMMENT] block [else_block] 
    . . .

It ends in an optional else_block, but nothing else. Your emulation is as good as you'll get I believe.

Upvotes: 6

Related Questions