Number: 10
Number: 20
Number: 30
Number: 40
Number: 50
16 Loops
Loops are control structures that allow us to execute a block of code repeatedly. Each executions is called an iteration. For example, when you count from 1 to 10, you are iterating over the numbers from 1 to 10.
Code within loops can be executed either a specific number of times (definite loop) or until a certain condition is met (indefinite loop).
In Python, there are two main loop structures:
forloops (definite loops)whileloops (indefinite loops)
Most of these structures can be used interchangeably, but each has its own use case.
16.1 Elements of a Loop
Loops consist of three main elements:
- Initialization. Set the initial value of the iteration variable. For example,
i = 1,count = 0, etc. - Stop Condition. Define the condition that stops the loop. For example,
i <= 10,count < 5, etc. - Increment/Decrement. Update the iteration variable to move to the next iteration. For example,
i += 1,count += 1, etc.
Loops add complexity to the program control flow. To better understand the execution sequence:
- Track your code line by line using a debugger.
- Check what each variable holds during execution.
16.2 Common Applications of Loops
In the following, we will cover different applications of loops in Python. Consider coming back to these examples after learning the details of each loop structure.
16.2.1 Iterating Over Lists or Collections
Loops allow you to process each element in a list or collection. For example:
- Processing each element in a list.
- Iterating over a range of numbers.
16.2.2 Calculating Aggregates
Each iteration can update a variable to calculate the aggregate. For example:
- Summing all numbers in a list.
- Counting the number of elements satisfying a specific condition.
def summary_statistics(numbers):
if len(numbers) == 0:
return 0, 0, 0
# Variables to store summary statistics
total = 0
count = 0
for num in numbers:
total += num
count += 1
average = total / count
return count, total, average
def test_summary_statistics():
assert summary_statistics([1, 2, 3, 4, 5]) == (5, 15, 3)
assert summary_statistics([10, 20, 30, 40, 50]) == (5, 150, 30)
assert summary_statistics([1, 1, 1, 1, 1]) == (5, 5, 1)
assert summary_statistics([]) == (0, 0, 0)
test_summary_statistics()16.2.3 Data Validation and Input
Loops can repeatedly prompt for user input until a valid value is entered. For example:
- Repeatedly asking for numbers within a range.
- Repeatedly asking for the correct input format of a password or list of arguments.
16.2.4 Searching and Filtering
Loops can be used to search for specific elements in a collection. For example:
- Finding the first occurrence of a value in a list.
- Filtering elements that meet a specific condition.
- Searching for the maximum or minimum value in a list.
- Finding the index of a specific element in a list.
def search_max_number(list):
if len(list) == 0:
return None
max_number = list[0]
for num in list:
if num > max_number:
max_number = num
return max_number
def test_search_max_number():
assert search_max_number([1, 2, 3, 4, 5]) == 5
assert search_max_number([5, 4, 3, 2, 1]) == 5
assert search_max_number([1, 3, 5, 2, 4]) == 5
assert search_max_number([1, 1, 1, 1, 1]) == 1
assert search_max_number([1]) == 1
assert search_max_number([]) == None
test_search_max_number()16.2.5 Generating Patterns or Sequences
With loops, the same code block can be executed multiple times to generate patterns or sequences. If the sequence obeys a logic that depends on the iteration number, loops are a good choice. For example:
- Calculating the factorial of a number (1 * 2 * 3 * … * n).
- Generating a sequence of prime numbers (see Listing 16.2).
range(2, 0) and range(2, 1) will not generate any prime numbers (range will return {python} list(range(2,0))).
def prime_numbers_until(n):
"""Generate prime numbers up to n.
A prime number is a number greater than 1 that has no
positive divisors other than 1 and itself.
Parameters:
----------
n : int
The upper limit of the prime numbers.
Returns:
-------
list
A list of prime numbers up to n.
"""
prime_numbers = []
for num in range(2, n):
is_prime = True
for i in range(2, num):
if num % i == 0:
is_prime = False
break
if is_prime:
prime_numbers.append(num)
return prime_numbers
def test_prime_numbers_until():
assert prime_numbers_until(0) == []
assert prime_numbers_until(1) == []
assert prime_numbers_until(2) == []
assert prime_numbers_until(10) == [2, 3, 5, 7]
assert prime_numbers_until(20) == [2, 3, 5, 7, 11, 13, 17, 19]
print(list(range(2,0)))
test_prime_numbers_until()[]
16.2.6 Repeating Actions
Loops can be used to repeat actions or apply the same operation to multiple elements. For example:
- Sending emails to a list of recipients.
- Applying a transformation to each item in a collection.
def send_email(email, subject, body):
# Code to send an email
print("Sending email to:", email)
print("Subject:", subject)
print("Body:", body)
def send_emails_example():
# List of tuples containing names and emails
contacts = [
("Alice", "alice@example.com"),
("Bob", "bob@example.com"),
("Charlie", "charlie@example.com"),
]
for name, email in contacts:
send_email(email, "Subject", f"Hello {name}, this is a test email.")
send_emails_example()Sending email to: alice@example.com
Subject: Subject
Body: Hello Alice, this is a test email.
Sending email to: bob@example.com
Subject: Subject
Body: Hello Bob, this is a test email.
Sending email to: charlie@example.com
Subject: Subject
Body: Hello Charlie, this is a test email.
16.3 Looping Statements
In the following sections, we will cover the different loop structures in Python. These structures allow you to repeat a block of code a specified number of times or until a certain condition is met.
The loop structures in Python are similar to those in other programming languages. If you learn loops in Python, you will be able to apply the same concepts in other languages like Java or C++.
16.4 for Loop (Definite)
When you know in advance how many times you want to execute a block of code, you can use a for loop. In this structure, the loop configuration, namely the initialization, stop condition, and increment, are defined in a single line, at the beginning of the loop. In Figure 16.1, we have the structure of a For loop. Notice that the condition is checked at the beginning of the loop. Then, the loop body is executed if the condition is True and the iteration variable is updated before checking the condition again.
graph LR
Start((Start))-->for
for --> LoopStart[Initialize<br>iteration variable<br>Define Stop Condition and <br>Configure Increment]
LoopStart-->Condition{Condition}
Condition-->|True|Statement1["`**Loop Body**
Statement 1
Statement 2
...
Statement N`"]
Statement1 --> ForNext["Update iteration
variable"]
ForNext --> Condition
Condition{Condition} ---->|False| End((End))
for loop. The loop is configured at the beginning, with the initialization, stop condition, and increment. The condition is checked at the beginning of the loop. Then, the loop body is executed if the condition is True. If the condition is False, the loop is exited. After executing the loop body, the iteration variable is updated before checking the condition again.
In the Listing 16.3, the for loop prints the numbers from 1 to 5. The range() function generates a sequence of numbers from the start value (inclusive) to the end value (exclusive). The parameters of the range() function are start, stop, and step:
start: The starting value of the sequence (default is 0).stop: The end value of the sequence (exclusive).step: The increment or decrement value (default is 1).
In Table 16.1, we show examples of using the range() function.
range() function.
| Function Call | Description | Output |
|---|---|---|
range(5) |
Generates numbers from 0 to 4 | 0, 1, 2, 3, 4 |
range(1, 6) |
Generates numbers from 1 to 5 | 1, 2, 3, 4, 5 |
range(1, 11, 2) |
Generates numbers from 1 to 10, incrementing by 2 | 1, 3, 5, 7, 9 |
range(5, 0, -1) |
Generates numbers from 5 to 1, decrementing by 1 | 5, 4, 3, 2, 1 |
for loop that prints the numbers from 1 to 5. The loop will run as long as i is less than 6.
The elements are as follows:
- Initialization:
i = 1. The loop variableiis initialized to 1. - Stop Condition:
i < 6. The loop will run as long asiis less than 6. - Increment:
i += 1. The loop variableiis incremented by 1 after each iteration.
16.4.1 Using Step in for Loop
In Python, the range() function can accept a step argument, allowing you to specify the increment or decrement value. For example, range(1, 11, 2) will generate numbers from 1 to 10, incrementing by 2.
Iteration 1
Iteration 3
Iteration 5
Iteration 7
Iteration 9
If you want to decrement the loop variable, you can use a negative value for step.
16.4.2 Nested Loops
Nested loops are loops within loops. They are useful when you need to perform multiple iterations based on different conditions.
When using nested loops, the inner loop will complete all its iterations before the outer loop moves to the next iteration.
For example:
Outer Loop: 1, Inner Loop: 1
Outer Loop: 1, Inner Loop: 2
Outer Loop: 2, Inner Loop: 1
Outer Loop: 2, Inner Loop: 2
Outer Loop: 3, Inner Loop: 1
Outer Loop: 3, Inner Loop: 2
16.5 for ... in Loop
The for ... in loop is used to iterate through elements of a collection or iterable object. With the for loop, you can process each item in a collection without knowing its size in advance.
for ... in loop that iterates over a list of fruits. The loop will run for each element in the list and print the name of the fruit.
16.6 while Loop (Indefinite)
This loop allows us to repeat a block of code until a certain condition is met. It can be used when the number of iterations is not known in advance.
In Figure 16.2, we have the structure of a while loop. Notice that the condition is checked at the beginning of the loop. Then, the loop body is executed if the condition is True.
graph LR
Start((Start)) --> LoopStart[Initialize<br>iteration variable]
LoopStart --> While[while]
While-->Condition{Condition}
Condition--True-->Statement1["`**Loop Body**
Statement 1
Statement 2
...
Statement N
_(Update iteration variable)_`"]
Statement1--->Condition
Condition ---->|False| End((End))
while loop. Notice that the condition is checked at the beginning of the loop. Then, the loop body is executed if the condition is True. If the condition is False, the loop is exited. Inside the loop, the iteration variable is updated before checking the condition again.
In the code example below, we have a while loop that prints the numbers from 1 to 5.
while loop that prints the numbers from 1 to 5. The loop will run as long as count is less than or equal to 5. First, the iteration variable count is initialized to 1. Then, the loop body is executed while count is less than or equal to 5. The loop body prints the value of count and increments count by 1. The loop stops when count is greater than 5.
Count: 1
Count: 2
Count: 3
Count: 4
Count: 5
16.6.1 Entering the Loop Before Checking the Stop Condition
Sometimes you want to ensure that the loop runs at least once. In this case, you can use a while True loop with a break statement. In Listing 16.5, we have a standard while loop that prints the numbers from 1 to 5. In Listing 16.6, we have a while True loop that prints the number 6. Notice that count starts with 6 (i.e., the stop condition is True) but the code block within the loop is executed nevertheless. This happens because the condition is checked at the end of the loop.
graph LR
Start((Start)) --> LoopStart[Initialize<br>iteration variable]
LoopStart --> While[while True]
While-->Statement1["`**Loop Body**
Statement 1
Statement 2
...
Statement N
_(Update iteration variable)_`"]
Statement1--->Condition -->|True| While
Condition{While<br>Condition} -->|False| End((End))
Do … Loop While loop, the loop body is executed before checking the stop condition. This allows the loop to run at least once, even if the stop condition is already met.
while True loop that prints the number 6. The iteration variable count is initialized to 6. The loop body prints the value of count and increments count by 1. The loop stops when count is equal to 5. Notice that the loop body is executed at least once, even if the stop condition is already met.
Checking the condition at the end is especially useful when you need to validate user input before entering the loop. For example, in the code below, the user is prompted to enter a number between 1 and 100. The loop will keep asking for input until a valid number is entered.
If we did not use a while True loop, we would need to duplicate the input prompt code before the loop to ensure that the loop runs at least once:
16.7 continue Statement
Sometimes you need to skip part of the code in a loop and continue to the next iteration. The continue statement:
- ends the current iteration in a loop, and
- continues to the next iteration.
Using continue, you can skip code for certain iterations.
Iteration 1
Skipping 2
Iteration 3
Skipping 4
Iteration 5
Whe can also use continue in a while loop. In the example below, we skip the number 3.
16.8 break Statement
Sometimes you need to exit a loop before it completes all iterations. To prematurely exit loops when a condition is met, you can use the break statement.
In Listing 16.7, we have a for loop that will break when i is equal to 5. In Listing 16.8, we have a while True loop that will break when count is greater than 5.
for loop that ends prematurely. The loop is supposed to run from 1 to 10, but it stops when i is equal to 5. The loop prints the numbers from 1 to 4 and then prints “Finished execution.”
while True loop that ends prematurely. The loop is supposed to run indefinitely, but it stops when count is greater than 5. The loop prints the numbers from 1 to 5 and then prints “Finished program.”
16.9 Exercises
16.9.1 Cumulative Sum of Numbers
Write a function named cumulative_sum_numbers that takes an integer n as input and returns the sum of all numbers from 1 to n.
16.9.2 Factorial of a Number
Write a function named factorial that takes an integer n as input and returns the factorial of n.
16.9.3 Calculate the Power of a Number
Write a function named power that takes two numbers, x and y, as input and returns x raised to the power of y. Use a loop to calculate the power.
16.9.4 Check Prime Number
Write a function named is_prime that takes an integer n as input and returns True if n is a prime number, otherwise returns False.
16.9.5 Average of Numbers
Write a function named avg_numbers that takes an integer n as input and returns the average of all numbers from 1 to n.
16.9.6 Sum of Odd Numbers
Write a function named sum_odd_numbers that takes an integer n as input and returns the sum of all odd numbers from 1 to n.
16.9.7 Print a Triangle Pattern
Write a function named print_triangle_pattern that prints a triangle pattern of asterisks (*) to the console.
The function takes as input:
n: an integer representing the height of the triangleside: a string, either"left"or"right"indicating the alignment of the triangle
And prints the triangle pattern of n lines aligned to the left or right.
def print_triangle_pattern(n, side):
pass # Add code here!
def test_print_triangle_pattern():
print("Left Aligned Triangle:")
print_triangle_pattern(4, "left")
# Expected output:
# *
# **
# ***
# ****
print("\nRight Aligned Triangle:")
print_triangle_pattern(4, "right")
# Expected output:
# *
# **
# ***
# ****16.9.8 Print an X Pattern
Write a function named print_x_pattern that takes an integer n as input and prints an “X” pattern of asterisks (*) to the console.
16.9.9 Reverse a String
Write a function named reverse_string that takes a string s as input and returns a new string with the characters of s reversed.
- Use
len()to get the size of the string. - Use slicing or loop to reverse the string.
16.9.10 Count Vowels in a String
Write a function named count_vowels that takes a string s as input and returns the count of vowels (A, E, I, O, U) in the string.
16.9.11 Remove Spaces from a String
Write a function named remove_spaces that takes a string s as input and returns a new string with all spaces removed. (Do not use string methods like replace or split.)
16.9.12 Print Two Different Numbers Within a Range
Write a function named two_different_numbers that takes two integer parameters, min_range and max_range. It returns two different random numbers within the specified range. Ensure the two generated numbers are different.
Use the random.randint(a, b) function to generate the numbers. For example, random.randint(1, 10) will generate a random number between 1 and 10, inclusive.
import random
def two_different_numbers(min_range, max_range):
# This code will generate random sequences
random.seed(400) # Change this number to get new sequences
pass # Add code here!
def test_two_different_numbers():
min_max = [(1, 10), (50, 100), (200, 300)]
for min_range, max_range in min_max:
a, b = two_different_numbers(min_range, max_range)
assert a != b
test_two_different_numbers()16.9.13 Find a Random Number Less Than 50
Write a function named find_random_number that repeatedly generates random numbers until it finds a number less than 50.
16.9.14 Generate a Random Prime Number
Write a function named generate_random_prime that repeatedly generates random numbers until it finds a prime number. Stop when a prime number is found, and print how many iterations it took to find the prime number.
Create a function is_prime to be used inside the loop.
import random
def is_prime(n):
pass # Add code here!
def generate_random_prime():
# This code will generate random sequences
random.seed(400) # Change this number to get new sequences
pass # Add code here!
def test_generate_random_prime():
generate_random_prime()
# Expected output with random seed 45:
# Random Prime Number: 67 / #Iterations: 1
# Expected output with random seed 7:
# Random Prime Number: 7 / #Iterations: 2
# Expected output with random seed 400:
# Random Prime Number: 53 / #Iterations: 616.9.15 Find the Largest Digit in a Number
Write a function named largest_digit that takes an integer n as input and returns the largest digit in n.