The else statement is one of the most commonly used control flow statement in Python. While it is common to some as just a conditional statement, it actually has many more uses. 

The statement is typically used to provide an alternative action in a section of the program's logic.

In this article we will explore all the cases where it is valid to use the else statement.

As a conditional statement

In Python, conditional statements are used to perform decisions. They make it possible to check if a certain condition is true or false, and then execute specific instructions depending on the result of the condition. The if, elif and else keywords are typically used in the implementation of conditional logic. There is a wide range of application of conditional statements.

The else statement is an essential part of the conditional logic. It is essentially used to provide an alternative outcome when the initial conditions are not met.

In if\else statement

for i in range(5):
     if i % 2 == 1:
         print(f"{i} is odd.")
     else:
         print(f"{i} is even.")

In the above example, we used the else in an if\else statement so that it will get executed if the current number is not odd.

In if\elif\else statement

score = 75

if score >= 90: 
    print("Excellent!")
elif score >= 80:
    print("Good Job!")
elif score >= 70:
    print("You can do better!")
else: 
    print("Keep Trying!")

Used this way, the  else gets executed when all the preceding if and elif conditions are not satisfied.

In assignment

num = 10
result = 'odd' if num % 2 == 1 else 'even'
print(result)

In the above example, conditional execution is in assignment so that if variable num is is odd string 'odd' is assigned to result, the else statement takes effect if the condition evaluates to False.

In list comprehension

a = [x if x%2==0 else None for x in range(10)]
print(a)

List comprehension is a convenient way to combine the features of conditional execution, looping and sequence building all in a one concise  syntax.

In the previous example, we have a list comprehension where we have defined a condition that if the current number is even, we append it to the resulting list, the else statement is used so that if the number is not even, we append None instead.

As a looping statement

Looping allows us to perform an action repeatedly until a specified condition fails. In Python, there are two basic loops, the for loop and the while loop.

Unlike most languages, Python allows the else statement to be used with loops.  The else statement can be used with both for and while loops. It will be executed when the loop terminates normally (when a break statement does not cause an exit from the loop). The statement can be used this way to to define a default action that will get executed if the loop terminates successfully.

With for loops

with a for loop

for i in range(10):
    print(i)
else:
    print("Finished")

In the above example, the else block gets executed because the loop terminates successfully, i.e without encountering any break statement. Consider the following example where a break statement causes the loop to terminate 

for i in range(10):
    print(i)
    if i == 5:
        break
else:
    print("Finished!")

As you can see above, the else block does not get executed because the for loop is terminated by a break statement rather than  exiting normally.

With while loops

Just like in for loops, the else statement can be used with while loop to perform an action if the loop exits normally.

i = 0
while i < 10:
    print(i ** 2)
    i += 1
else:
    print("We are done!")

Similarly, if the while loop terminates due to a break statement, the else block will be skipped.

i = 0
while i < 10:
    if i > 5:
        break
    print(i ** 2)
    i += 1
else:
    print("Done!")

In exception handling

Exception handling allows us to  handle errors gracefully instead of crashing the program. In Python, it is primarily achieved using the try/except statement. The statement enables us to catch exception as they are raised, perform a  corrective action if necessary and generally make sure that the program recovers from errors instead of crashing.

The following example shows a simplified use of the try/except statement.

try:
    print(a + b) #undifined variables
except:
    print("An error occurred!")

In the above example, we used undefined variables a and b, this then means that a NameError exception was raised.  The except block above acts as a catch-all block such that if any error is raised in the try block, it will be handled inside it. 

The else statement is used with the try/except statement to perform an action if  no potential exception was raised.  In other words it only gets executed if no exception was propagated to an except block. This is useful when the program should take a certain action if the code in the try block runs successfully.

try:
   print(*range(5), sep = '\n')
except:
    print("An error occurred.!")
else:
    print("No error occurred")

In the above example, no exception is raised in  the try block thus the else block gets executed.  Consider the following example where an exception is raised.

try:
     a = 10
     b = 0
     print(a/b)
except ZeroDivisionError:
     print("Can't divide by zero.")
else:
     print("No error occurred")

As you can see above, the else block is not executed because an exception(ZeroDivisionError) was raised.