# Zimo Li

Today, I learned that you can pair an `else` clause with a loop statement such as `for` or `while`. It looks like this:

``````for i in iterator:
# do something
else:
# do something else
``````

This may look quite counterintuitive for the first time, but we will unwrap it in a moment! ✨

First, let's review the basic syntax of a `for` loop in Python. A `for` loop allows you to iterate over an iterator (such as a list, tuple, or string) and execute a block of code for each value. Here's an example:

``````fruits = ['apple', 'banana', 'cherry']
for fruit in fruits:
print(fruit)
``````

This code would output:

``````apple
banana
cherry
``````

# Simple example

Now, let's add an `else` clause to this loop:

``````fruits = ['apple', 'banana', 'cherry']
for fruit in fruits:
print(fruit)
else:
print("No more fruits")
``````

This code would output:

``````apple
banana
cherry
No more fruits
``````

In this case, the `else` block is executed after the `for` loop has finished normally. If the loop is exited early (for example, by a `break` statement), the `else` block will not be executed.

# Linear search example

This `for..else` can be quite helpful in some scenarios. For example, you can use it to check if a value exists in a list:

``````values = [1, 2, 3, 4, 5]
for value in values:
if value == 6:
print("Value found!")
break
else:
``````

Let's take a look at another version without using `for...else`:

``````values = [1, 2, 3, 4, 5]

found = False
for value in values:
if value == 6:
found = True
break

if found:
print("Value found!")
else:
``````

You can see, we have to introduce a boolean flag if we do not use the `else` clause. This makes the control flow more complex.

# Breaking out of nested loops

In Python, the `break` statement only terminates the nearest enclosing loop. In some cases, you may want to break out of a parent loop.

Consider this code that determines if `n` is a prime number:

``````n = 11

if n <= 1:
print(f"{n} is not a prime number!")
exit()

for i in range(2, n):
for j in range(2, n):
if i * j == n:
print(f"{n} is not a prime number!")
break
else:
continue # only executed if the inner loop did NOT break
break # only executed if the inner loop DID break
else:
print(f"{n} is a prime number!")
``````

It works by iterating over all pairs of numbers `(i, j)` less than `n` and checking if the product of any of them is equal to `n`. In the case where we find `i * j` is equal to `n`, we can say that `n` is not a prime number and we would want to exit the outer `for` loop early.

If the inner loop completes successfully (i.e., without breaking), it means that no pairs of numbers were found whose product equals `n`. In this case, the `else` clause of the inner loop is executed. This `else` clause triggers the `continue` statement, which causes the outer loop to immediately proceed to the next value of `i` without executing the remaining code in the outer loop.

If the inner loop breaks at any point, the `else` clause of the inner loop is skipped and the outer loop would reach the `break` statement, which breaks the outer loop as well.

PEP 3136 is a Python Enhancement Proposal that proposes support for labels in `break` and `continue` statements. However, it was rejected due to the complexity it would add to Python.

The example I have shown above is one of the workarounds that produce clean code. Another solution is to put the code in a function and use `return` instead. Using a function is usually preferred because code with low cyclomatic complexity is usually more maintainable.