# Python Programming/Decision Control

Python, like many other computer programming languages, uses Boolean
logic for its decision control. That is, the Python interpreter compares
one or more values in order to decide whether to execute a piece of code
or not, given the proper syntax and instructions.

Decision control is then divided into two major categories, conditional
and repetition. Conditional logic simply uses the keyword **if** and a
Boolean expression to decide whether or not to execute a code block.
Repetition builds on the conditional constructs by giving us a simple
method in which to repeat a block of code while a Boolean expression
evaluates to *true*.

## Boolean Expressions

Here is a little example of boolean expressions (you don\'t have to type
it in):

``` python
a = 6
b = 7
c = 42
print (1, a == 6)
print (2, a == 7)
print (3, a == 6 and b == 7)
print (4, a == 7 and b == 7)
print (5, not a == 7 and b == 7)
print (6, a == 7 or b == 7)
print (7, a == 7 or b == 6)
print (8, not (a == 7 and b == 6))
print (9, not a == 7 and b == 6)
```

With the output being:

    1 True
    2 False
    3 True
    4 False
    5 True
    6 True
    7 False
    8 True
    9 False

What is going on? The program consists of a bunch of funny looking
`print` statements. Each `print` statement prints a number and an
expression. The number is to help keep track of which statement I am
dealing with. Notice how each expression ends up being either True or
False; these are built-in Python values. The lines:

``` python
print (1, a == 6)
print (2, a == 7)
```

print out True and False respectively, just as expected, since the first
is true and the second is false. The third print,
`print (3, a == 6 and b == 7)`, is a little different. The operator
`and` means if both the statement before and the statement after are
true then the whole expression is true otherwise the whole expression is
false. The next line, `print (4, a == 7 and b == 7)`, shows how if part
of an `and` expression is false, the whole thing is false. The behavior
of `and` can be summarized as follows:

  expression        result
  ----------------- --------
  true and true     true
  true and false    false
  false and true    false
  false and false   false

Note that if the first expression is false Python does not check the
second expression since it knows the whole expression is false.

The next line, `print (5, not a == 7 and b == 7)`, uses the `not`
operator. `not` just gives the opposite of the expression (The
expression could be rewritten as `print (5, a != 7 and b == 7)`).
Here\'s the table:

  expression   result
  ------------ --------
  not true     false
  not false    true

The two following lines, `print (6, a == 7 or b == 7)` and
`print (7, a == 7 or b == 6)`, use the `or` operator. The `or` operator
returns true if the first expression is true, or if the second
expression is true or both are true. If neither are true it returns
false. Here\'s the table:

  expression       result
  ---------------- --------
  true or true     true
  true or false    true
  false or true    true
  false or false   false

Note that if the first expression is true Python doesn\'t check the
second expression since it knows the whole expression is true. This
works since `or` is true if at least one of the expressions are true.
The first part is true so the second part could be either false or true,
but the whole expression is still true.

The next two lines, `print (8, not (a == 7 and b == 6))` and
`print (9, not a == 7 and b == 6)`, show that parentheses can be used to
group expressions and force one part to be evaluated first. Notice that
the parentheses changed the expression from false to true. This occurred
since the parentheses forced the `not` to apply to the whole expression
instead of just the `a == 7` portion.

Here is an example of using a boolean expression:

``` python
list = ["Life","The Universe","Everything","Jack","Jill","Life","Jill"]

# Make a copy of the list.
copy = list[:]
# Sort the copy
copy.sort()
prev = copy[0]
del copy[0]

count = 0

# Go through the list searching for a match
while count < len(copy) and copy[count] != prev:
    prev = copy[count]
    count = count + 1

# If a match was not found then count can't be < len
# since the while loop continues while count is < len
# and no match is found
if count < len(copy):
    print ("First Match:",prev)
```

See the Lists chapter to explain
what \[:\] means on the first line.

Here is the output:

    First Match: Jill

This program works by continuing to check for a match
`while count < len(copy) and copy[count] != prev`. When either `count`
is greater than the last index of `copy` or a match has been found the
`and` is no longer true so the loop exits. The `if` simply checks to
make sure that the `while` exited because a match was found.

The other \'trick\' of `and` is used in this example. If you look at the
table for `and` notice that the third entry is \"false and won\'t
check\". If `count >= len(copy)` (in other words `count < len(copy)` is
false) then copy\[count\] is never looked at. This is because Python
knows that if the first is false then they both can\'t be true. This is
known as a short circuit and is useful if the second half of the `and`
will cause an error if something is wrong. I used the first expression
(`count < len(copy)`) to check and see if `count` was a valid index for
`copy`. (If you don\'t believe me remove the matches \`Jill\' and
\`Life\', check that it still works and then reverse the order of
`count < len(copy) and copy[count] != prev` to
`copy[count] != prev and count < len(copy)`.)

Boolean expressions can be used when you need to check two or more
different things at once.

## Examples

password1.py

``` python
## This programs asks a user for a name and a password.
# It then checks them to make sure that the user is allowed in.
# Note that this is a simple and insecure example,
# real password code should never be implemented this way.

name = raw_input("What is your name? ")
password = raw_input("What is the password? ")
if name == "Josh" and password == "Friday":
    print ("Welcome Josh")
elif name == "Fred" and password == "Rock":
    print ("Welcome Fred")
else:
    print ("I don't know you.")
```

Sample runs

    What is your name? Josh
    What is the password? Friday
    Welcome Josh

    What is your name? Bill
    What is the password? Saturday
    I don't know you.

## Exercises

1.  Write a program that has a user guess your name, but they only get 3
    chances to do so until the program quits.

Solutions

