There are tons of cases when we are looking for a value in a list of elements and would like to be able to indicate when we could not find that value.
In most of the languages it is a bit cumbersome.
Find the first match
For example this very simple example in which we are looking for an even number:
examples/python/for_else/find_even_number.py
numbers = [3, 4, 5]
for n in numbers:
if n % 2 == 0:
even = n
break
print(even)
If we run this program it will set the name even
to be 4 which is what we wanted.
The problem is that if there is no match (there is no even number) then the variable even
will never get a value and thus it will be undeclared.
examples/python/for_else/no_even_number.py
numbers = [3, 5]
for n in numbers:
if n % 2 == 0:
even = n
break
print(even)
Running this program will result in the following exception:
$ python no_even_number.py
Traceback (most recent call last):
File "no_even_number.py", line 8, in <module>
print(even)
NameError: name 'even' is not defined
Default value outside the loop
One solution to this problem employed in most programming languages is to
set a default value to the even
variable before we enter the loop.
That way if we pass all the values without finding a match, the variable even
already has a value:
examples/python/for_else/default_result.py
numbers = [3, 5]
even = None
for n in numbers:
if n % 2 == 0:
even = n
break
print(even)
$ python default_result.py
None
for-else
A more elegant way that can be written in Python is the use of else
after the for
-loop.
examples/python/for_else/for_else.py
numbers = [3, 5]
for n in numbers:
if n % 2 == 0:
even = n
break
else:
even = None
print(even)
The code in the else
part will be executed if the loop has finished normally, without calling break
.
That mean if we find a match during our loop, assign it to even
and leave the loop calling break
then the else
part won't be executed.
Together with the name- or variable-scoping of Python this will result in the same effect, but in my humble opinion a more elegant way.