Sunday, July 16, 2017

Summer of code 2017: Python, Day 29 Else after For and While loops


As explained in my Summer of code 2017: Python post I decided to pick up Python

This is officially day 29. today I decided to take a look at how an Else block works with For and While loops in Python. This is not how you would expect it to work if you are coming to Python from another language.


Take a look at the following code

for i in range(5):
    print(i)
else:
    print('else')

What do you think will happen? Will the else part be printed?

Let's run it

    >>> for i in range(5):
...     print(i)
... else:
...     print('else')
... 
0
1
2
3
4
else
>>> 

So after the for loop finished, the else block gets executed. To me that was very surprising, I had not expected this.


What will happen if we put a break in the loop, now the code looks like this

for i in range(5):
    print(i)
    if i == 2:
        break
else:
    print('else')

What do you think happens now? Let's executed it

>>> for i in range(5):
...     print(i)
...     if i == 2:
...         break
... else:
...     print('else')
... 
0
1
2
>>> 

Interestingly the else block did not get executed, this is because the else will only execute if the loop completed

From the docs(I have made the relevant part bold)

The for statement is used to iterate over the elements of a sequence (such as a string, tuple or list) or other iterable object:
for_stmt ::= "for" target_list "in" expression_list ":" suite ["else" ":" suite]
The expression list is evaluated once; it should yield an iterable object. An iterator is created for the result of the expression_list. The suite is then executed once for each item provided by the iterator, in the order of ascending indices. Each item in turn is assigned to the target list using the standard rules for assignments, and then the suite is executed.

When the items are exhausted (which is immediately when the sequence is empty), the suite in the else clause, if present, is executed, and the loop terminates.
A break statement executed in the first suite terminates the loop without executing the else clause's suite. A continue statement executed in the first suite skips the rest of the suite and continues with the next item, or with the else clause if there was no next item.




Let's look at what happens when the sequence is empty now

>>> for i in []:
...     print(i)
... else:
...     print('else')
... 
else
>>> 

As you can see the else block get executed

If you have a while loop that is initially false, the else block will also get executed

>>> while False:
...     print('it is false')
... else:
...     print('else')
... 
else
>>> 

So why does Python have this? One way is to know that you have executed the loop all the way to the end of the loop without having run a break statement.

Take a look at this silly example

>>> x = 10
>>> for i in range(5):
...     if i == x:
...         print('x found')
...         break
... else:
...     print('x not found')
... 
x not found
>>> 


As you can see the else block is executed and we can see that x was not found. Now normally you would store the state in a variable or you would have a helper function that would return false instead.

So that is all for today. Next up is unit testing in Python






No comments: