<style>
.markdown-body h1:first-of-type {
margin-top: 24px;
}
.markdown-body h1 {
margin-top: 64px;
}
.markdown-body h1 + h2 {
margin-top: 32px;
}
.markdown-body h2 {
margin-top: 48px;
}
.markdown-body h2.topics {
font-size: 1.8em;
border-bottom: none;
}
.markdown-body h3 {
color: cornflowerblue;
}
.markdown-body p strong {
font-weight: normal;
color: red;
}
.exercise {
font-size: 150%;
font-weight: bold;
color: rgb(227,112,183);
}
.note {
color: red;
}
.reveal {
background-color: black;
margin-bottom: 16px;
}
.reveal p {
color: black;
padding-left: 16px;
font-size: 16px;
transition: color 1s ease;
}
.reveal:hover p {
color: white;
}
</style>
# ACIT 1515 - Lesson 4
<h2 class="topics">Topics</h2>
- [Review](#Review)
- [While Loops](#While-Loops)
- [While Loop Conditions](#While-Loop-Conditions)
- [Nested While Loops](#Nested-While-Loops)
- [Infinite While Loops](#Infinite-While-Loops)
## Review
Conditional statements (also called "if" statements) allow us to run code *conditionally*, depending on whether a condition is true or false.
A basic conditional statement has to:
1. Start with the `if` keyword
2. Followed by a ==condition==
3. Followed by a colon
4. Followed by one or more **indented** lines
Conditions can be one of three things:
1. A *comparison* between two values that results in a boolean value (True or False)
```python=
x = 10
y = 5
if x > y:
print('X is greater than y')
```
2. A *test* that results in a boolean value
```python=
keyword = 'CIT'
course = 'ACIT1515'
if keyword in course:
print('CIT was found in the course')
```
3. or, a boolean value itself
```python=
understands = True
if understands:
print("Now you're getting it")
```
If a boolean condition results in the value `True`, any code indented underneath will run. If the boolean condition results in the value `False`, any code indented below is skipped.
### Rules Of Conditional Statements
When we have a group of conditional statements, **only one 'block' can run**: the first condition that returns `True` or the `else` block if present.
Recall that there is a specific order to if, elif, and else blocks. Groups of conditional statements must:
1. Always start with a single, mandatory `if`
2. Followed by multiple optional `elif` blocks
3. Followed by a single optional `else` block
## While Loops
In contrast to a conditional statement, which runs a block of indented statements *once* if a boolean condition is true, a ==while== loop allows us to run a block of indented statements **repeatedly** until a boolean condition becomes **False**. This allows us to repeatedly perform a task until we get to a desired state or outcome.
In previous examples and assignments we have asked a user to enter a value, for example an assignment number:
```python=
number = input('Please enter the assignment number: ')
```
If the value they entered was *not numeric*, we have then used a conditional statement to end the program and print a help message:
```python=
import sys
assignment = input('Please enter the assignment number: ')
if not assignment.isnumeric():
sys.exit('Invalid assignment number')
```
The code above works well to prevent the program from crashing, but it isn't a great experience for the user. Ideally we would like to give them as many chances as they need to enter a valid value, and then allow the program to continue. This is an example of a task that we can run repeatedly using a `while` loop.
To create a `while` loop, we use the `while` keyword followed by a condition, followed by a colon. Any statement(s) that we want to run repeatedly must be *indented* underneath the `while` statement.
The `while` loop will repeatedly run any indented statements until the condition becomes False. Once the condition returns False, the loop stops and the rest of the script continues to execute.
Here is an example of a simple conditional statement that allows us to repeatedly prompt a user for an assignment number:
```python=
while True:
assignment = input('Please enter the assignment number: ')
if assignment.isnumeric():
break
else:
print('Assignment number must be numeric')
print('Thank you for entering a valid assignment number')
```
This loop repeatedly prompts the user for an assignment number, then checks the value. If the string value they entered is not numeric, a help message is printed and the user is again asked to enter an assignment number.
Note that the loop is considered finished when the **first unindented line is seen by the Python interpreter**. Indentation is very important in Python and we often need multiple levels of indentation to distinguish between different 'blocks' of statements. In short: be consistent and exacting with your indentation!
Notice also how our condition is simply the boolean value `True`! If a while loop repeatedly runs any indented statements until the boolean condition becomes False, how do we stop this loop?
Because our boolean condition (the value `True`) can never become False, we have to *manually* stop the loop using the ==break== keyword. The `break` keyword on line 5 causes the loop to stop when the user enters a numeric string, and the script continues at line 7.
If the user never enters a numeric keyword, the loop never stops and the program continually asks for a valid numeric assignment number.
### While Loop Conditions
As shown above, we can use a boolean *value* as our condition, provided we manually stop the loop using the `break` keyword. As in conditional statements, we can also use *comparisons* and functions that return a boolean value as the conditions for our `while` loops. Below are two examples:
Using a comparison as a `while` loop condition:
```python=
counter = 10
while counter >= 0:
print(counter)
counter = counter - 1
```
Using a function that returns a boolean value as a `while` loop condition:
```python=
assignment = input('Please enter assignment number: ')
while not assignment.isnumeric():
print('Assignment number must be numeric')
assignment = input('Please enter assignment number: ')
print('Thank you for entering a valid assignment number')
```
### Nested While Loops
If necessary, we can *nest* `while` loops (place a loop inside another loop), just as we can nest conditional statements:
```python=
import random
keep_playing = True
while keep_playing:
number = random.randint(1, 10)
while True:
guess = input('Guess a number between 1 and 10')
if guess.isnumeric() and int(guess) == number:
print('You guessed correctly!')
break
else:
print('Incorrect guess!')
print('Do you want to try again?')
response = input('Type n to quit, any other key to continue')
if response == 'n':
keep_playing = False
print('Thank you for playing')
```
At the beginning of the outer loop (`while keep_playing`), we generate a random number between 1 and 10. Then, an inner loop begins where we repeatedly ask the user to guess a number. If the string they enter is numeric, and equal to the random number we generated, we break out of the inner loop and go to line 17. Lines 17 to 21 ask the user if they want to try again - if they type 'n', the outer loop is stopped by setting the boolean condition (the `keep_playing` variable) to False, otherwise the entire process begins again at line 6!
### Infinite While Loops
A final note about `while` loops: it is important when writing a `while` loop to always ensure the loop can stop somehow, either via a `break` statement or by ensuring your boolean condition will eventually become `False`. If not, you can get stuck in what is referred to as an 'infinite' loop - it nevers stop!
See the example below for a condition that a) can never become `False` and b) never breaks:
```python=
counter = 10
while counter >= 0:
counter = counter + 1
print(counter)
```
The above loop never stops because the value of the `counter` variable will *always* be greater than or equal to zero. The current value of counter will be incremented by one and printed to the terminal until the program is forcibly stopped (for example by the user typing ctrl-c). Regardless of what type of boolean condition you use (comparison, function, or value), ensure that you have a way of stopping your `while` loop.