\chapter{Conditionals}
\label{lecture-conditionals}

\section{Boolean values and expressions}

The Python type for storing true and false values is called bool,
named after the British mathematician, George Boole. George Boole
created \emph{Boolean algebra} , which is the basis of all modern
computer arithmetic. There are only two \myidx{boolean values} :
\pythoninline{True} and \pythoninline{False}. Capitalization is
important, since \pythoninline{true} and \pythoninline{false} are not
boolean values. 

\begin{pythonInteractive}
>>> type(True)
<type 'bool'>
>>> type(true)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'true' is not defined
\end{pythonInteractive}

A \myidx{boolean expression} is an expression that evaluates to a
boolean value. The operator \pythoninline{==} compares two values and
produces a boolean value: 
\begin{pythonInteractive}
>>> 5 == 5
True
>>> 5 == 6
False
\end{pythonInteractive}

In the first statement, the two operands are equal, so the expression
evaluates to \pythoninline{True}; in the second statement, 5 is not
equal to 6, so we get \pythoninline{False}. The \pythoninline{==}
operator is one of the \myidx{comparison operators}; the others are:  
\begin{python}
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 than or equal to y
x <= y               # x is less than or equal to y
\end{python}

Although these operations are probably familiar to you, the Python
symbols are different from the mathematical symbols. A common error is
to use a single equal sign (\pythoninline{=}) instead of a double equal sign
(\pythoninline{==}). Remember that \pythoninline{=} is an assignment
operator and \pythoninline{==} is a comparison
operator. Also, there is no such thing as =$<$ or =$>$.

\section{Logical operators}

There are three \myidx{logical operators} : \pythoninline{and},
\pythoninline{or}, and \pythoninline{not}. The
semantics (meaning) of these operators is similar to their meaning in
English. For example, \pythoninline{x $>$ 0 and x $<$ 10} is true only
if \pythoninline{x} is greater than 0 \emph{and} less than 10.
\pythoninline{n \% 2 == 0 or n \% 3 == 0} is true if \emph{either} (or
both) of
the conditions is true, that is, if the number is divisible by 2
\emph{or} 3.
Finally, the \pythoninline{not} operator negates a boolean expression,
so \pythoninline{not(x $>$ y)} is true if \pythoninline{(x $>$ y)} is
false, that is, if x is less than or equal to y.

% insert a table of truth values here for testing understanding
 % (mini-test)
\begin{figure}[h]
\centering
\begin{tabular}{|l|l|l|c|c|}
\hline
x&y&z&Boolean Expression&Value\\
\hline
\pythoninline{True}&-&-&\pythoninline{x}&\\
\pythoninline{True}&\pythoninline{True}&-&\pythoninline{x or y}&\\
\pythoninline{True}&\pythoninline{False}&-&\pythoninline{x and y}&\\
\pythoninline{True}&\pythoninline{False}&\pythoninline{True}&
\pythoninline{x and (y or z)}&\\
\pythoninline{10}&\pythoninline{5}&\pythoninline{7}&\pythoninline{(x<y) or (y<z)}&\\
\pythoninline{10}&\pythoninline{5}&\pythoninline{7}&\pythoninline{(x<y)
and (y<z)}&\\
\pythoninline{10}&\pythoninline{5}&\pythoninline{7}&\pythoninline{(x<y) and (y<x)}&\\
\pythoninline{10}&\pythoninline{5}&\pythoninline{7}&\pythoninline{(x<y) or (y<z)}&\\
\pythoninline{10}&\pythoninline{10}&\pythoninline{7}&\pythoninline{(x<y) or (y<z)}&\\
\pythoninline{10}&\pythoninline{10}&\pythoninline{7}&\pythoninline{((x<y) or (y<z)) and ((x<20) and (y>5))}&\\
\hline
\end{tabular}
\caption{Test your knowledge of Boolean expressions}
\end{figure}

\section{Conditional execution}
In order to write useful programs, we almost always need the ability
to check conditions and change the behaviour of the program
accordingly. \myidx{Conditional statements} give us this ability. The
simplest form is the \myidx{if statement} :
\begin{python}
if x > 0:
    print "x is positive"
\end{python}
The boolean expression after the if statement is called the
\myidx{condition} . If it is true, then the indented statement gets
executed. If not, nothing happens.
The syntax for an if statement looks like this:
\begin{python}
if BOOLEAN EXPRESSION:
    STATEMENTS
\end{python}

As with the function definition from Lecture \ref{lec-functions-1} and
other compound statements, the \pythoninline{if} statement consists of
a header and a body. The header begins with the keyword
\pythoninline{if} followed by a \emph{boolean expression} and ends
with a colon (\pythoninline{:}).  The indented statements that follow
are called a \myidx{block} . The first unindented statement marks the
end of the block. A statement block inside a compound statement is
called the \myidx{body} of the statement.  Each of the statements
inside the body are executed in order if the boolean expression
evaluates to \pythoninline{True}. The entire block is skipped if the
boolean expression evaluates to \pythoninline{False}.  There is no
limit on the number of statements that can appear in the body of an if
statement, but there has to be at least one.

% removed by BJM
% This is almost always a bad idea and leads to bad style unless used
 % wisely. A common style error made by beginning programmers (and
 % even not so beginning ones) is to pepper their code with empty ifs.
% Occasionally, it is useful to have a body with no statements
% (usually as a place keeper for code you haven't written yet). In that
% case, you can use the pass statement, which does nothing.
% \begin{python}
% if True:          # This is always true
%     pass          # so this is always executed, but it does nothing
% \end{python}

\section{Alternative execution}

A second form of the if statement is alternative execution, in which
there are two possibilities and the condition determines which one
gets executed. The syntax looks like this:
\begin{python}
if x % 2 == 0:
    print x, "is even"
else:
    print x, "is odd"
\end{python}

If the remainder when \pythoninline{x} is divided by \pythoninline{2}
is \pythoninline{0}, then we know that \pythoninline{x} is 
even, and the program displays a message to that effect. If the
condition is false, the second set of statements is executed. Since
the condition must be true or false, exactly one of the alternatives
will be executed. The alternatives are called \myidx{branches} ,
because they are branches in the flow of execution.

As an aside, if you need to check the parity (evenness or oddness) of
numbers often, you might wrap this code in a function:
\begin{python}
def print_parity(x):
    if x % 2 == 0:
        print x, "is even"
    else:
        print x, "is odd"
\end{python}
For any value of x, \pythoninline{print\_parity} displays an appropriate
message. When you call it, you can provide any integer expression as
an argument.
\begin{pythonInteractive}
>>> print_parity(17)
17 is odd.
>>> y = 41
>>> print_parity(y+1)
42 is even.
\end{pythonInteractive}

\section{Chained conditionals}
Sometimes there are more than two possibilities and we need more than
two branches. One way to express a computation like that is a
\myidx{chained conditional}:
\begin{python}
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"
\end{python}
\pythoninline{elif} is an abbreviation of else if. Again, exactly one
branch will be executed. There is no limit to the number of
\pythoninline{elif} statements but only a single (and optional) else
statement is allowed and it must be the last branch in the statement:
\begin{python}
if choice == 'a':
    function_a()
elif choice == 'b':
    function_b()
elif choice == 'c':
    function_c()
else:
    print "Invalid choice."
\end{python}
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.

\section{Nested conditionals}
One conditional can also be \myidx{nested} within another. Consider
the following example:
\begin{python}
if x == y:
    print x, "and", y, "are equal"
else:
    if x < y:
        print x, "is less than", y
    else:
        print x, "is greater than", y
\end{python}

The outer conditional contains two branches. The first branch contains
a simple output statement. The second branch contains another if
statement, which has two branches of its own. Those two branches are
both output statements, although they could have been conditional
statements as well.
Although the indentation of the statements makes the structure
apparent, nested conditionals become difficult to read very
quickly. A nested conditional can always be rewritten as a chained
conditional and vice versa. What to use is partly a matter of choice,
but in general you should use the structure that is easiest to
understand. 

Logical operators often provide a way to simplify nested conditional
statements. For example, we can rewrite the following code using a
single conditional:
\begin{python}
if 0 < x:
    if x < 10:
        print "x is a positive single digit."
\end{python}
The print statement is executed only if we make it past both the
conditionals, so we can use the \emph{and} operator:
\begin{python}
if 0 < x and x < 10:
    print "x is a positive single digit."
\end{python}
These kinds of conditions are common, so Python provides an
alternative syntax that is similar to mathematical notation:
\begin{python}
if 0 < x < 10:
    print "x is a positive single digit."
\end{python}
This condition is semantically the same as the compound boolean
expression and the nested conditional.

\newpage
\section{Booleans and type conversion}

For boolean values, type conversion is especially interesting:
\begin{pythonInteractive}
>>> str(True)
'True'
>>> str(true)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'true' is not defined
>>> bool(1)
True
>>> bool(0)
False
>>> bool("False")
True
>>> bool("")
False
>>> bool(3.14159)
True
>>> bool(0.0)
False
\end{pythonInteractive}
Python assigns boolean values to values of other types. For numerical
types like integers and floating-points, zero values are false and
non-zero values are true. For strings, empty strings are false and
non-empty strings are true.

\section{Glossary}
\begin{description}
\item[boolean value:]There are exactly two boolean values: True and
  False. Boolean values result when a boolean expression is evaluated
  by the Python interpreter. They have type bool.
\item[boolean expression:]An expression that is either true or false.
\item[bool function:]Converts the argument to a boolean.
\item[comparison operator:] One of the operators that compares two
  values: ==, !=, $>$, $<$, $>$=, and $<$=.
\item[logical operator:]One of the operators that combines boolean
  expressions: and, or, and not.
\item[conditional statement:]A statement that controls the flow of
  execution depending on some condition. In Python the keywords if,
  elif, and else are used for conditional statements.
\item[condition:]The boolean expression in a conditional statement
  that determines which branch is executed.
\item[block:]A group of consecutive statements with the same
  indentation.
\item[body:]The block of statements in a compound statement that
  follows the header.
\item[branch:]One of the possible paths of the flow of execution
  determined by conditional execution.
\item[chained conditional:]A conditional branch with more than two
  possible flows of execution. In Python chained conditionals are
  written with \pythoninline{if ... elif ... else} statements.
\item[nesting:]One program structure within another, such as a
  conditional statement inside a branch of another conditional
  statement.
\end{description}

\section{Laboratory exercises}
\begin{enumerate}

\item

\begin{python}
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"
\end{python}
\emph{Wrap} this code in a function called \pythoninline{compare(x, y)}. Call
\pythoninline{compare} three times: one each where the first argument
is less than, 
greater than, and equal to the second argument.

\item To better understand boolean expressions, it is helpful to construct
truth tables. Two boolean expressions are \emph{logically
equivalent} if they have the same truth table.
The following Python script prints out the truth table for any
boolean expression in two variables \pythoninline{p} and
\pythoninline{q}:
\begin{python}
expression = raw_input("Enter a boolean expression in 2 variables, p and q: ")

print "p       q       " + expression
length = len("p       q       " + expression) + 2
print length * "-"

p = True
q = True
print str(p) + "\t" + str(q) + "\t" + str(eval(expression))

p = True
q = False
print str(p) + "\t" + str(q) + "\t" + str(eval(expression))

p = False
q = True
print str(p) + "\t" + str(q) + "\t" + str(eval(expression))

p = False
q = False
print str(p) + "\t" + str(q) + "\t" + str(eval(expression))
\end{python}

There is a new function in the above script: \pythoninline{eval}
\emph{evaluates} its argument as a python expression. You can use
\pythoninline{eval} to evaluate arbitrary strings. Let's find out more
about boolean expressions. Copy this program to a file named
\pythoninline{boolean\_ex.py}, then run it and give it: \pythoninline{p
or q}, when prompted for a boolean expression. You should get the
following output:
\begin{pythonOutput}
Enter a boolean expression in 2 variables, p and q: p or q
 p       q      p or q
----------------------
True	True	True
True	False	True
False	True	True
False	False	False
\end{pythonOutput}

\newpage
Now that we see how it works, let's wrap it in a function to make it
easier to use (save the altered code as a new file called
\pythoninline{boolean\_fun.py}):
\begin{python}
def show_boolean_expression(p, q, expression):
    print str(p) + "\t" + str(q) + "\t" + str(eval(expression))

def show_truth_table(expression):
    print " p       q      " + expression
    length = len(" p       q      " + expression)
    print length * "-"
    
    show_boolean_expression(True, True, expression)
    show_boolean_expression(True, False, expression)
    show_boolean_expression(False, True, expression)
    show_boolean_expression(False, False, expression)
\end{python}
We can \myidx{import} it into a Python shell and call
\pythoninline{show\_truth\_table} with a
string containing our boolean expression in \pythoninline{p} and
\pythoninline{q} as an argument: 
\begin{pythonInteractive}
>>> from boolean_fun import *
>>> show_truth_table("p or q")
 p       q      p or q
----------------------
True	True	True
True	False	True
False	True	True
False	False	False
>>>
\end{pythonInteractive}

Use the \pythoninline{show\_truth\_table} functions with the following
boolean expressions, recording the truth table produced each time:
\begin{enumerate}
\item not(p or q)
\begin{answerspace}



zend
\end{answerspace}
\item p and q
\begin{answerspace}



zend
\end{answerspace}

\newpage
\item not(p and q)
\begin{answerspace}



zend
\end{answerspace}
\item not(p) or not(q)
\begin{answerspace}



zend
\end{answerspace}
\item not(p) and not(q)
\begin{answerspace}



zend
\end{answerspace}
\end{enumerate}
Which of these are logically equivalent?

\item Look at the following expressions. What do you think the results
  would be? Enter the expressions in to the Python interpreter to
  check your predictions.
\begin{python}
True or False
True and False
not(False) and True
\end{python}

What do you think will be returned by these expressions? Again check
using the interpreter. Do you understand why you are getting the
results you are?
\begin{python}
True or 7
False or 7
True and 0
False or 8
\end{python}

Finally what will be returned by these expressions? The results may
surprise you. 
\begin{python}
"happy" and "sad"
"happy" or "sad"
"" and "sad"
"happy" and ""
\end{python}

Analyze these results. What observations can you make about values
of different types and logical operators? Can you write these
observations in the form of simple \emph{rules} about
\pythoninline{and} and \pythoninline{or} expressions?
\begin{answerspace}





zend
\end{answerspace}

\item

\begin{python}
if choice == 'a':
    function_a()
elif choice == 'b':
    function_b()
elif choice == 'c':
    function_c()
else:
    print "Invalid choice."
\end{python}

Wrap this code in a function called \pythoninline{dispatch(choice)}. Then define
\pythoninline{function\_a}, \pythoninline{function\_b}, and
\pythoninline{function\_c} so that they print out a
message saying they were called. For example:
\begin{python}
def function_a():
    print "function_a was called..."
\end{python}

Put the four functions (\pythoninline{dispatch},
\pythoninline{function\_a}, \pythoninline{function\_b}, and
\pythoninline{function\_c}) into a script named
\pythoninline{choice.py}. At the bottom of this
script add a call to \pythoninline{dispatch('b')}. Your output should be:
\begin{pythonOutput}
function_b was called...
\end{pythonOutput}

Finally, modify the script so that user can enter 'a', 'b', or
'c'. Test it by importing your script into the Python shell.

\item Write a function named \pythoninline{is\_divisible\_by\_3} that
takes a single 
integer as an argument and prints ``This number is divisible by
three.'' if the argument is evenly divisible by 3 and ``This number
is not divisible by three.'' otherwise.

Now write a similar function named \pythoninline{is\_divisible\_by\_5}.

\item Generalize the functions you wrote in the previous exercise into a
function named \pythoninline{is\_divisible\_by\_n(x, n)} that takes two integer
arguments and prints out whether the first is divisible by the
second. Save this in a file named \pythoninline{is\_divisible.py}. Import it
into a shell and try it out. A sample session might look like this:
\begin{pythonInteractive}
>>> from is_divisible import *
>>> is_divisible_by_n(20, 4)
Yes, 20 is divisible by 4
>>> is_divisible_by_n(21, 8)
No, 21 is not divisible by 8
\end{pythonInteractive}

\newpage
\item What will be the output of the following?
\begin{python}
if "Ni!":
    print 'We are the Knights who say, "Ni!"'
else:
    print "Stop it! No more of this!"

if 0:
    print "And now for something completely different..."
else:
    print "What's all this, then?"
\end{python}
Explain what happened and why it happened.
\begin{answerspace}



zend
\end{answerspace}

\item Try to finish the game (there are twelve levels) that you have
  been playing in previous labs.
  % 10: getting harder, 11: hardest? functions calling functions
  % 12: anticlimax - only need one function

\end{enumerate}

\submitreminder
