Lecture 06 - While and For Loops
In our last lecture, we covered conditional statements:
if statement: Executes a block of code if a condition is True.elif statement: Checks a new condition if previous if or elif conditions were False.else statement: Executes a block of code if all preceding if and elif conditions were False.We also looked at:
and, or, not.if statements: Placing one if statement inside another for more complex decision-making.Remember this kind of structure?
The ability to control program flow based on conditions is very important, and loops will build upon this by allowing us to repeat actions.
for loop?for loop is a way to iterate over a sequence of elementsif statement, including the colon : and the necessary indentation (4 spaces)for loop?list_ids = ["KIA", "Ferrari", "Ford", "Tesla"]
print("Dear customer, we are writing about your " + list_ids[0] + " car.")
print("Dear customer, we are writing about your " + list_ids[1] + " car.")
print("Dear customer, we are writing about your " + list_ids[2] + " car.")
print("Dear customer, we are writing about your " + list_ids[3] + " car.")Dear customer, we are writing about your KIA car.
Dear customer, we are writing about your Ferrari car.
Dear customer, we are writing about your Ford car.
Dear customer, we are writing about your Tesla car.
Dear customer, we are writing about your KIA car.
Dear customer, we are writing about your Ferrari car.
Dear customer, we are writing about your Ford car.
Dear customer, we are writing about your Tesla car.
This code iterates over each element in list_ids and three additional elements: ‘a’, ‘b’, and ‘c’.
The + operator is used to concatenate list_ids with another list ['a', 'b', 'c'].
For each element in this combined list, the loop assigns the element to the variable id and then prints it out using the print function.
range()The range() function is often used with for loops to generate a sequence of numbers.
range(stop): Generates numbers from 0 up to (but not including) stop.
range(start, stop): Generates numbers from start up to (but not including) stop.
range(start, stop, step): Generates numbers from start up to (but not including) stop, with an increment of step.
enumerate()Sometimes you need both the index and the value of an item in a sequence. The enumerate() function provides this:
Syntax: for index, value in enumerate(sequence):
Index 0: apple
Index 1: banana
Index 2: cherry
You can also specify a starting index for enumerate(): enumerate(fruits, start=1)
index = 1 before the loop (just to start at 1, since Python indexes start at 0)index = index + 1 at the end of the bodyWe are out of the loop 1
Dear customer, your position is 1 on the waitlist and your car brand is KIA
We are inside the loop 2
Dear customer, your position is 2 on the waitlist and your car brand is Ferrari
We are inside the loop 3
Dear customer, your position is 3 on the waitlist and your car brand is Ford
We are inside the loop 4
Dear customer, your position is 4 on the waitlist and your car brand is Tesla
We are inside the loop 5
Dear customer, your position is 1 on the waitlist and your car brand is KIA
Dear customer, your position is 2 on the waitlist and your car brand is Ferrari
Dear customer, your position is 3 on the waitlist and your car brand is Ford
Dear customer, your position is 4 on the waitlist and your car brand is Tesla
range(len(list_ids)) does?str(i+1) do?for loopsimport pandas as pd
import matplotlib.pyplot as plt
carfeatures = pd.read_csv("data/features.csv")
list_vars = ["acceleration","weight"]
variable_name = "acceleration"
plt.scatter(x = carfeatures[variable_name],
y = carfeatures["mpg"])
plt.ylabel("mpg")
plt.xlabel(variable_name)
plt.show()
variable_name = "weight"
plt.scatter(x = carfeatures[variable_name],
y = carfeatures["mpg"])
plt.ylabel("mpg")
plt.xlabel(variable_name)
plt.show()carfeatures = pd.read_csv("data/features.csv")
list_vars = ["acceleration","weight"]
index = 1
for variable_name in list_vars:
plt.scatter(x = carfeatures[variable_name], y = carfeatures["mpg"])
plt.ylabel("mpg")
plt.xlabel(variable_name)
plt.title("Figure " + str(index))
plt.show()
index = index + 1# Create a list of x-values list_x = [1,2,4,5, ..., 50]
# Create a list of y-values to fill in later.
list_x = [1,2,4,5,6,7,8,9,10]
list_y = [None] * len(list_x)
# Create an index
index = 0
for x in list_x:
list_y[index] = list_x[index]**2 + 2*list_x[index]
index = index + 1
# Display results visually
print(list_y)
plt.scatter(list_x, list_y)
plt.xlabel("X-axis")
plt.ylabel("Y-axis")
plt.title("Scatter plot of Y = X^2 + 2X")
plt.show()[3, 8, 24, 35, 48, 63, 80, 99, 120]
append# Create a list of x-values list_x = [1,2,4,5, ..., 50]
# Start an empty list of y-values with []
list_x = [1,2,4,5,6,7,8,9,10]
list_y = []
# Create an index
for x in list_x:
y = x**2 + 2*x
list_y.append(y)
# Display results visually
print(list_y)
plt.scatter(list_x, list_y)
plt.xlabel("X-axis")
plt.ylabel("Y-axis")[3, 8, 24, 35, 48, 63, 80, 99, 120]
Text(0, 0.5, 'Y-axis')
data folder:
features.csvworldbank_wdi_2019.csvlist_datasets and assign it a list with the two dataset namespd.read_csv()while loop?while loop is used to iterate over a block of code as long as the test expression (condition) is Truewhile loops when we don’t know the number of times to iterate beforehand, or when the iteration depends on a condition being metwhile vs forfor loop:
while loop:
False.while loop: simple counter exampleThis while loop acts like for i in range(5):
Count is: 0
Count is: 1
Count is: 2
Count is: 3
Count is: 4
Loop finished.
If count = count + 1 is forgotten, it creates an infinite loop!
while loop: user input validationwhile loops are great for repeatedly asking for user input until it’s valid
# Example: Get a positive number from the user
number = -1 # Initialise to a value that fails the condition
while number <= 0:
try:
user_input = input("Please enter a positive number: ")
number = float(user_input) # Try to convert to float
if number <= 0:
print("That's not a positive number. Try again.")
except ValueError:
print("Invalid input. Please enter a number.")
print(f"You entered a valid positive number: {number}")(This code is best run in an interactive Python session.)
A common pitfall with while loops is creating an infinite loop! - This happens if the condition in the while statement never becomes False - Cause: Often due to forgetting to update the variable(s) involved in the condition within the loop
Example of an infinite loop (DO NOT RUN THIS CELL AS IS 😅):
Ctrl+C in the terminal, or using the “Interrupt Kernel” button in Jupyter).list_fruits = ["apple", "banana", "cherry", "date", "elderberry"]while loop to access the fruit at the current index and print the fruit namePython provides statements to control the flow of execution within loops:
break: Terminates the current loop prematurely and transfers control to the statement immediately following the loop.continue: Skips the rest of the code inside the current iteration of the loop and proceeds to the next iteration.else clause in loops: An optional block that executes if the loop completes all its iterations without encountering a break statement.break statementbreak statement is used to exit a for or while loop immediately, regardless of whether the loop’s condition is still true or if there are more items to iterate overExample: Find the first non-integer element in a list and stop the loop
list_mixed = [1, 2, "text_message", 5, 10.5]
for value in list_mixed:
if not isinstance(value, int): # Check if value is NOT an integer
print(f"Stopped: Found a non-integer element: '{value}' (type: {type(value).__name__})")
break # Exit the loop
print(f"Processing integer: {value}")
print("Loop finished or broken.")Processing integer: 1
Processing integer: 2
Stopped: Found a non-integer element: 'text_message' (type: str)
Loop finished or broken.
continue statementcontinue statement is used to skip the remaining code inside the current iteration of a loop and move to the next iterationExample: Print only integers from a list and skip non-integer elements
Integer found: 1
Integer found: 2
Skipping non-integer: 'text_message'
Integer found: 5
Skipping non-integer: '10.5'
Skipping non-integer: 'another_string'
Integer found: 7
Loop finished processing all elements.
else clausefor and while loops can have an optional else clauseelse block is executed if and only if the loop terminates normally (i.e., not by a break statement)Example with for and else: Searching for an item
my_numbers = [1, 3, 5, 7, 9]
search_for = 6
for num in my_numbers:
if num == search_for:
print(f"Found {search_for} in the list.")
break
else: # Executed if the loop completes without a break
print(f"{search_for} was not found in the list.")
search_for = 5 # Try again with a number that is in the list
for num in my_numbers:
if num == search_for:
print(f"Found {search_for} in the list.")
break
else:
print(f"{search_for} was not found in the list.")6 was not found in the list.
Found 5 in the list.
for loop (and sometimes an if condition) but in a single line of code.new_list = [expression for item in iterable]Advantages:
for loop with append()Example 1: Customised Messages
['Your car model is: KIA', 'Your car model is: Ferrari', 'Your car model is: Ford', 'Your car model is: Tesla']
Example 2: Math operations
You can add an if condition to filter items during list creation.
if: new_list = [expression for item in iterable if condition]Example: Create a list of squares of only the even numbers from 0 to 9.
Squares of even numbers from 0-9: [0, 4, 16, 36, 64]
You have a list of names: names = ["Alice", "Bob", "Charlie", "David", "Eve", "Fiona", "George"]
short_names that contains only the names from the names list that have 5 or fewer characters.uppercase_long_names that contains the uppercase versions of names from the names list that have more than 5 characters.range(len(list_ids)):
len(list_ids) gets the length (number of items) in the list_ids list.range() then creates a sequence of numbers from 0 up to (but not including) that length.str(i+1):
i is the current loop index, starting at 0.i+1 adds 1 to that index so that the position number starts at 1. (Remember: Python indexes start at 0.)str() converts the resulting number to a string[2].i starts at 0, but we want to display position numbers starting at 1 for the customers.So, this code loops through each item in list_ids, printing a message for each customer that includes: - Their position (index + 1) - The corresponding car brand from list_ids
The loop will run once for each item in list_ids, with i taking on values from 0 to len(list_ids) - 1.
Descriptive statistics for features.csv:
mpg cylinders displacement weight acceleration
count 398.000000 398.000000 398.000000 398.000000 398.000000
mean 23.514573 5.454774 193.427136 2970.424623 15.568090
std 7.815984 1.701004 104.268683 846.841774 2.757689
min 9.000000 3.000000 68.000000 1613.000000 8.000000
25% 17.500000 4.000000 104.250000 2223.750000 13.825000
50% 23.000000 4.000000 148.500000 2803.500000 15.500000
75% 29.000000 8.000000 262.000000 3608.000000 17.175000
max 46.600000 8.000000 455.000000 5140.000000 24.800000
Descriptive statistics for worldbank_wdi_2019.csv:
life_expectancy gdp_per_capita_usd
count 252.000000 255.000000
mean 72.682931 17230.949757
std 7.382636 25792.183785
min 52.910000 216.972968
25% 67.109750 2186.046581
50% 73.599000 6837.717826
75% 78.234892 19809.323135
max 85.078049 199377.481800
apple
banana
cherry
date
elderberry
Solution for the list comprehension “Try it yourself!” exercise:
names = ["Alice", "Bob", "Charlie", "David", "Eve", "Fiona", "George"]
# 1. Names with 5 or fewer characters
short_names = [name for name in names if len(name) <= 5]
print(f"Original names: {names}")
print(f"Short names (<= 5 chars): {short_names}")
# 2. Uppercase versions of names longer than 5 characters
uppercase_long_names = [name.upper() for name in names if len(name) > 5]
print(f"Uppercase long names (> 5 chars): {uppercase_long_names}")Original names: ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Fiona', 'George']
Short names (<= 5 chars): ['Alice', 'Bob', 'David', 'Eve', 'Fiona']
Uppercase long names (> 5 chars): ['CHARLIE', 'GEORGE']