Clause else
the misunderstood and despised.
Always when we think about else
associate immediately with blocks if
, as Luciano Ramalho says in his book Python fluent, "The clause else
is an underused feature of the language, it can be used not only in commands if
, but also in commands for
, while
and try
."
Try:
In the case of the use of else
in try/except
, the block else
will only be executed if no exception is raised in the block try
, according to the documentation, exceptions raised in the block else
shall not be dealt with by the clauses execpt
previous.
An example of Try block usage:
try:
chamada_arriscada()
pos_chamada()
except OSError:
log('OSError...')
Technically speaking the above code is not wrong, but put pos_chamada()
inside the block try
without good reason renders the code dubious and/or obscure, for the sake of clarity a block try
should contain only commands that can generate exceptions, so it is best to do:
try:
chamada_arriscada()
except OSError:
log('OSError...')
else:
pos_chamada()
For:
The block else
will only be executed after the end of the loop for
, if there is an interruption by a break
, for example, the block after the else
will not be executed.
While:
Again the block else
will not be executed if while is interrupted for a break
, that is to say, else
shall be waived only if the while
end on condition that it has become false.
If in either case an exception or a command return
, break
or continue
occur and make the control exit the main loop, the clause else
will be ignored.
Again quoting Luciano Ramalho, I agree with him when he says:
I think else
a poor choice of reserved word in all cases, except with if
. It implies an exclusionary alternative, such as "perform this loop; otherwise, do that", but the semantics of else
in loops is the opposite of this: "perform this loop, then do that". This suggests that then
would be a better reserved word - and would also make sense in the context of Try: "Try this and then do that". However adding new reserved words can break a lot of existing code, and Guido avoids it as if it were a plague.
Note: Guido refers to Guido van Rossum, the creator of language.
Edited: Following @Guilherme Nascimento’s comment, I added examples and explanation for the links for
and while
. TL;DR
Preambulo for examples with for
and while
:
It is difficult to give a specific or "real" example, because it would be necessary to explain the context, so I created a generic example that may seem kind of "nonsense", but it is based on a real case. Let’s assume that we received a list of any operation that we will use later in our code, but first we need to normalize it (make each item between 0 and 1) if the number 7 nay appear in this list. For this, let’s first create the normalization function:
def normalize(lst):
sum_lst = sum(lst)
norm_lst = []
for n in range(len(lst)):
norm_lst.append(lst[n]/sum_lst)
return norm_lst
Now let’s create 2 lists one where appears the number 7 (in this case the function normalize nay should be called) and another where it does not appear.
lista1, lista2 = [1,2,3,6,7,9], [1,3,5,9,44,55]
Example with the use of for
:
To be more practical, let’s define a function that receives the list and check if there is a presence of the element that avoids the call to normalization, in case the number 7 and then we test with the two lists created previously:
# Loop for
def test_for(lst):
for item in lst:
if item == 7:
break
else:
return normalize(lst)
return lst
Testing with the list1:
test_for(lista1)
Exit:
[1, 2, 3, 6, 7, 9]
Note that as the main loop was interrupted by break
(to lista1
has the number 7), the normalization function has not been called.
Testing with the Lista2:
test_for(lista2)
Exit:
[0.008547008547008548,
0.02564102564102564,
0.042735042735042736,
0.07692307692307693,
0.37606837606837606,
0.4700854700854701]
Now as the lista2
does not contain the number 7, the loop for
was executed to the end, testing all elements of the list and then the normalization function was called in the block after the else
.
Example using the loop while
:
Just like we did with for
, let’s define a function to test the loop while
:
# Loop While
def test_while(lst):
n = 1
while n <= len(lst)-1:
if lst[n-1] == 7:
break
n+=1
else:
return normalize(lst)
return lst
Testing with the lista1
test_while(lista1)
Exit:
[1, 2, 3, 6, 7, 9]
Again, as this list contains the number 7, the normalization function was not called, as the main loop (while
) was not executed until the end, was interrupted by break
in the penultimate item on the list.
Testing with the lista2
:
test_while(lista2)
Exit:
[0.008547008547008548,
0.02564102564102564,
0.042735042735042736,
0.07692307692307693,
0.37606837606837606,
0.4700854700854701]
In this case the while loop was executed until the end, that is, until the variable n
did not meet the condition of the loop n
less than or equal to the number of elements in the list, that is, all elements in the list have been tested, then the clause else
was executed.
See working on repl.it.
The explanation about for e while was sensational, already has my +1, I would ask you to add examples with "exit" explanation comments, would enrich and facilitate the understanding of who this started.
– Guilherme Nascimento
@Guilhermenascimento I created a fictional example, the "real" examples I have would be meaningless out of context, but I think I was able to elucidate a little more.
– Sidon