2018.02.13

# Conditional Execution

• Sometimes we want to do something contingent on something else.

• We can use the two distinct values of boolean type to decide whether to do it.

• In Python we do this with an `if` statement.

``````if <boolean_expression> :
<first_conditional_statement>
⋮
<last_conditional_statement>``````
• The indented block of statements is called a branch.

• The boolean expression above it is called the branch guard.

• If the branch guard evaluates to `True` then the branch is run.

• Otherwise, it is skipped.

``````if input ('Are you my friend? ') == 'yes' :
print ('Hi friend!')``````

# Alternative Execution

• Sometimes we want one of two things to happen, depending on some condition.

• We can do this by adding an `else` clause to our `if` statement:

``````if <guard_expression> :
<true_branch>
else :
<false_branch>``````
• If the guard expression evaluates to `True` then the true branch is run.

• Otherwise, the false branch is run.

• Notice that exactly one branch is always run.

``````if input ('Are you my friend? ') == 'yes' :
print ('Hi friend!')
else :
print ('Hello stranger!')``````

# Chained Conditionals

• We can combine `if` and `else` clauses to run the first branch whose guard evaluates to `True`:

``````if <first_guard> :
<first_branch>
else :
if <second_guard> :
<second_branch>
else :
⋮
else:
if <last_guard> :
<last_branch>``````
• But this pattern is so common that it has a built-in shorthand, the `elif` clause:

``````if <first_guard> :
<first_branch>
elif <second_guard> :
<second_branch>
⋮
elif <last_guard> :
<last_branch>``````
• The guards are tested in order.

• Only the branch corresponding to the first guard that evaluates to `True` is run.

• Notice that at most one branch is run.

# Multiple Alternatives

We can add an `else` clause to a chained conditional:

``````if <first_guard> :
<first_branch>
elif <second_guard> :
<second_branch>
⋮
elif <last_guard> :
<last_branch>
else :
<default_branch>``````
• The branch of the `else` clause is the default branch. It is run if all of the other branch guards evaluate to `False`.

• Like an if-else statement, exactly branch is always run.

• This is equivalent to:

``````if <first_guard> :
<first_branch>
elif <second_guard> :
<second_branch>
⋮
elif <last_guard> :
<last_branch>
elif True :
<default_branch>``````

# General Form of `if` Statements

The most general form of an `if` statement has:

• exactly one `if` clause,

• zero or more `elif` clauses,

• zero or one `else` clauses.

# Example: Guessing Game

Let’s think of something and have Python guess what it is.

``````def guessing_game () :
if input ('is it an animal? ') == 'yes' :
if input ('does it have legs? ') == 'yes' :
print ('then it must be a centipede!')
else :
print ('then it must be a shark!')
elif input ('is it a vegetable? ') == 'yes' :
if input ('does your mom make you eat it? ') == 'yes' :
print ('then it must be broccoli!')
else :
print ('then it must be a pumpkin!')
elif input ('is it a mineral? ') == 'yes' :
if input ('is it shiny? ') == 'yes' :
print ('then it must be gold!')
else :
print ('then it must be mud!')
else :
print ('then I give up!')``````

# Complex Conditionals

The branching structure of conditionals can be arbitrarily complex.

But complicated conditional statements can get confusing: How do we know if it’s a leap year?

``````def leap_deep (year) :
if year % 4 == 0 :
if year % 100 == 0 :
if year % 400 == 0 :
print (str (year) + ' is a leap year')
else :
print (str (year) + ' is not a leap year')
else :
print (str (year) + ' is a leap year')
else :
print (str (year) + ' is not a leap year')``````

Boolean expressions help to simplify conditional structure.

``````def leap_flat (year) :
if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0 :
print (str (year) + ' is a leap year')
else :
print (str (year) + ' is not a leap year')``````

# Conditional Expressions

You can also write conditional expressions:

``<true_expression> if <boolean_guard> else <false_expression>``
• It evaluates to the expression on the left is the guard evaluates to `True`,
• otherwise, it evaluates to the expression on the right.

``````def min (x , y) :
if x <= y :
return x
else :
return y``````

we can write:

``````def min (x , y) :
return x if x <= y else y``````

Tip: If you want to become a really good programmer, look for opportunities to replace statements with expressions.

Expressions are more flexible because they are data that can be manipulated by your program, in contrast, statements can only be executed.

# Repeated Execution

• An `if` statement executes a code block at most one time, depending on whether the guard is satisfied.

• Another control structure, called a `while` statement, executes a block any number of times, as long as the guard is satisfied.

``````while <boolean_expression> :
<first_loop_statement>
⋮
<last_loop_statement>``````
• The indented block of statements is called the loop body.

• The boolean expression above it is called the loop guard.

# How While Loops are Executed

``````i  =  0
print ("Here we go...")
while i < 3 :
print ('One more time!')
i = i + 1
print ("O.K. I'm done now.")``````

When control reaches a `while` statement:

• The loop guard is evaluated.
• If the guard’s value is `False` then the body is skipped.
• Otherwise, control passes into the body.
• Control flows normally within the loop body.
• After the last statement of the body, control returns to the guard, and this process is repeated.

# Example: Computing Factorial by Iteration

We can compute the factorial (mathematical) function (i.e. $n! = n × (n−1) × (n−2) × ⋯ × 1$) by iteration.

``````def factorial (n) :
"""
signature: int -> int
precondition: n >= 0
returns the factorial of the argument
"""
acc  =  1
while n > 0 :
acc  =  acc * n
n  =  n - 1
return acc``````
• The variable “`n`” is a loop variable.

• It is part of the guard and gets updated during the body of the loop.

• The variable “`acc`” is an accumulator.

• It stores the running partial result of the value computed by the loop.

• When we’re finished repeating the loop, the accumulator should contain the value we want.

# Augmented Assignment

• In the loop body of the factorial function we updated both the loop variable and the accumulator based on their previous values.

• There is a shorthand for this common pattern:

``````def factorial (n) :
acc  =  1
while n > 0 :
acc  *=  n  #  same as: acc  =  acc * n
n  -=  1    #  same as: n  =  n - 1
return acc``````
• The expressions “`acc *= n`” and “`n -= 1`” are called augmented assignments.

• They are shorthand for “`acc = acc * n`” and “`n = n - 1`” respectively.

• There are augmented assignment forms for the operators `{+ , - , * , / , // , % , **}`.

# Drawing Polygons using Iteration

• Last week we learned how to draw a square using Python’s turtle:

``````def square (size) :
turtle.forward (size)
turtle.left (90.0)
turtle.forward (size)
turtle.left (90.0)
turtle.forward (size)
turtle.left (90.0)
turtle.forward (size)
turtle.left (90.0)``````
• This got pretty repetitive.

• We can streamline this definition using a `while` loop.

``````def square (size) :
sides_drawn  =  0
while sides_drawn < 4 :
turtle.forward (size)
turtle.left (90.0)
sides_drawn  +=  1``````

# Validating User Input

Using loops and conditionals together we can validate user input:

• A predicate function for days of the week:

``````def is_weekday (day) :
# signature: str -> bool
return \
day == 'Sunday'   or day == 'Monday' or day == 'Tuesday' or day == 'Wednesday' or \
day == 'Thursday' or day == 'Friday' or day == 'Saturday'``````
• A function to take valid input from the user:

``````def get_day_of_week () :
# signature: () -> str ; returns a day of the week entered by the user and validated by is_weekday.
while True :
day = input ('What day is it (Sunday through Saturday)? ')
if is_weekday (day) :
return day
else :
print ('Sorry, but "' + day + '" is not a day of the week.')``````
• A function that decides what to do based on user input:

``````def what_to_do () :
# signature: () -> NoneType
day = get_day_of_week ()    #  here we know that day will be a valid day of the week
if day == 'Saturday' or day == 'Sunday' :
print ("I'm sleeping in.")
else :
print ('Better get up and go to class.')``````