# Chapter 5 – Conditionals and recursion

Hi there,

The tip to read the chapter once (and taking notes on where I might find some obstacles) and then read it again a second time helped me tremendously.

The impression of “déjà vu” makes my second reading far more efficient. I am aiming to pick-up some speed with this reading tactic.

5.1 Modulus operator

A couple of months ago, I had to refresh my memory in order to explain the concept of remainder. However, I never thought that this concept would be helpful learning Python as well.

Wikipedia provides a full and comprehensive explanation of the modulo operation. I recommend to read it.

Basically, a remainder is the number that is left when you divide two numbers that are not multiples.

Modulo operation finds the remainder of a division

In Python, the modulus operator is the percent sign %.

If the remainder of x divided by y is zero, then we infer that x is divisible by y or x is a multiple of y.

Multiple and Factors

The book provides a clear example:

>>> quotient = 7/3
>>> print quotient
2
>>> remainder = 7 % 3
>>> print remainder
1

5.1 Boolean expressions

A Boolean expression is an expression that is either true or false.

The operator == compares two operands and verify whether they are equal or not.

>>> 5 == 5
True

>>> 5 == 6
False

If we verify the type of True and False, we discover that they belong to the type bool.

>>> type (True)<type ‘bool’>

>>> type (False)
<type ‘bool’>

Relational operators :

• x == y   # x is equal to y
• x !=  y   # x is not equal to y
• x > y   # x is greater than y
• x < y   # x is less than y
• x >= y   # x is greater or equal to y
• x <= y   # x is less or equal to y

A common error is to use a single equal sign (=) instead of a double equal sign ( == ). Remember that (=) is an assignment operator and ( == ) is a relational operator.

x = y    # x gets the value of y

versus

x == y    # x is equal to y

Who is Boole? George Boole was an English mathematician, philosopher and logician of the 19th century. You may click on his name in order to find out more about him.

5.3 Logical operators

• and
x > 0 and x < 10 is true if both relations are true
• or
x > 0 or x < 10 is true if either relation is true
• not
The not operator negates a Boolean expression.
not ( x < 10 ) is true if x is greater than 10 and it is false if x is less than 10.

5.4 Conditional execution

This is where the fun starts.

Conditional statements provide Python users with the ability to to check conditions and change the behaviour of the program accordingly.

Conditional execution

There is no limit on the number of statements that can appear in the body, but there has to be at least one.

As we advance and write more elaborate functions and eventually programs, there is a useful statement called pass which does nothing. It is a place keeper for code to be written.

For instance:

if x < 0:    pass       # code to be written at a later time

5.5. Alternative execution

The alternative execution provides two (2) possibilities and the condition determines which one gets executed.

This is a second form of the if statement. The syntax looks like this:

if x % 2 == 0:    print ‘x is even’
else:
print ‘x is odd’

The condition can either be true or false. So only one alternative will be executed.

The alternatives are called branches, because they are branches in the flow of execution.

5.6 Chained conditionals

When we have more than two possibilities, then we need more than two branches. Chained conditionals enable us to express a computation with more than two alternatives.

if x < y :    print ‘x is less than y
elif x > y :
print ‘x is greater than y
else:
print ‘x and y are equal’

As soon as Python finds a True Boolean expression, then the branch will be executed.

elif

• It is the abbreviation of “else if”.
• There is no limit on the number of elif statements.

else

• If there is an else statement, it has to be at the end.
• The else statement is optional.

Python’s flow of execution:

Each condition is checked in order. If the first is false, the next is checked, and so on. If one of them is true, the corresponding branch executes, and the statement ends. Even if more than one condition is true, only the first true branch executes.

5.7 Nested conditionals

Conditionals can also be nested within another. This concept reminded me of the nested functions we saw on Chapter 3 and the Matryoshka image.

Python Nested Conditionals

Love-Hate relationship with nested conditionals:

Love: Indentation provides nested conditionals with an apparent structure.

Hate: Beware, it is easy to get frustrated trying to find indentation bugs.

The author, Allen B. Downey points out that nested conditionals become difficult to read at a glance.

Logical operators often provide a way to simplify nested conditionals.

Nested conditionals versus logical operators

NOTE: In this chapter, the author used the word trichotomy. I looked up in Wikipedia and it means “splitting into three parts”.

5.8 Recursion

In the Python world, a function can call another function and a function can call itself as well.

A function that calls itself is recursive; the process is called recursion.

Recursive function with a return statement

5.9 Stack diagrams for recursive functions

Stack diagrams are helpful to illustrate a function call or a recursive function.

Every time a function gets called, Python creates a new function frame, which contains the function’s local variables and parameters. For a recursive function, there might be more than one frame on the stack at the same time.

Think Python: Exercise 5.1

Exercise 5.2

Let us make a break and laugh a bit.

When I read this exercise I had the impression I was in the same situation as this:

School and Homework verus Exam questions

Source: So Relatable

Here is the question:

Write a function called do_n that takes a function object and a number, n, as arguments, and that calls the given function n times.

What blocked me was the expression “function object“. So, I had to go back to Chapter 3 (p.22 and p. 29) to recall the definition.

A function object is a value you can assign to a variable or pass as an argument. For example, do_twice is a function that takes a function object as an argument and calls it twice:

def do_twice ( f ):
f ( )

f ( )

Here is an example that uses do_twice to call a function named print_spam twice.

def print_spam( ):    print ‘spam’

do_twice ( print_spam )

Inspiring me from this reference, here is what I found:

>>> def do_n (f, n):
…     if n <= 0:
…             return
…     else:
…             f()
…             do_n(f, n-1)

>>> def lyrics ():
…     print “I’m singing in the rain ”

>>> do_n (lyrics, 3)
I’m singing in the rain
I’m singing in the rain
I’m singing in the rain
>>>

5.10 Infinite recursion

If a recursion never reaches a base case, it goes on making recursive calls forever, and the program never terminates. This is known as infinite recursion, and it is generally not a good idea.

Once Python reaches 1000 recurse frames on the stack it will report an error.

5.11 Keyboard input

We will begin to write code blocks that require the user to interact.

In Python 2: raw_input function

In Python 3: input function

When this function is called, the program stops and waits for the user to type something. When the user presses “Enter“, the program resumes and raw_input returns what the user typed as a string.

When you ask the user for some input. It is best to state the question. For instance:

>>> sports = raw_input (‘Do you play any volley-ball or football?’\n’)
volleyball

>>> print sports
volleyball

The sequence \n at the end of the prompt represents a newline, which is a special character that causes a line break. That is why the user’s input appears below the prompt.

By default, the user’s answers are considered stings. However, we can change that like this:

>>> prompt = “What is the speed of sound in meters per second in dry air?\n”
>>> speed_sound = raw_input(prompt)
What is the speed of sound in meters per second in dry air?
343.2

>>> speed_sound
‘343.2’
>>> float(speed_sound)
343.2
>>>

5.12 Debugging

Python provides a hints for debugging such as:

• What kind of error it was, and
• Where it occurred.

Beware of these mistakes because they are a bit tricky to find:

• whitespace errors: spaces and tabs are invisible to Python
• runtime errors: watch for integer numbers versus floating numbers when dividing.

Python can indicate the line where the error occurred. However, verify the previous lines as well in order to correct the error more quickly.

So, this is it for the theory of chapter 5!

It does not matter how slowly you go, so long as you do not stop — Confucius, Chinese philosopher (551 BC – 479 BC)

***

### Acknowledgments :

These notes represent my understanding from the book Think Python: How to Think Like a Computer Scientist written by Allen B. Downey.

Part of the chapter is transcribed and all the quotes unless specified otherwise come directly from his book.

Thank you Professor Downey for making this knowledge available.

Also, I would like to thank the open source community for their valuable contribution in making resources on programming available.

Thank you