In data science, a lot of the processes that you’ll run using Python code will be iterative and repetitive. Things like discounts in a store, interest rates in a bank or even taxes for various line items will need to be calculated under specific conditions across hundreds or even millions of data rows. While you can code manually for each instance that you need data to be processed, things can snowball in a bad way real quick. Coding for everything is insanely work intensive and it overcomplicates your code, making it more demanding on system resources. Fortunately, there’s an easy way to do things.
Enter: loops. In Python programming, this element plays a crucial role by allowing developers to execute a block of code repeatedly under controlled conditions. This repetitive execution is fundamental to automating tasks, processing data, and handling repetitive operations efficiently. In essence, loops make it possible to perform millions of operations in seconds, a feat that is indispensable in modern software development.
Known for its ease of use and readability, Python provides various types of loops to handle different scenarios in programming. Loops in Python are straightforward to understand and implement, making them an excellent tool for both beginners and experienced programmers to leverage in their code.
Loops are typically used to:
- Execute code as long as a condition remains true.
- Iterate over items in a collection (like lists, tuples, or dictionaries) to perform operations on each element.
- Repeatedly perform an operation until a specific condition changes.
Understanding how to effectively use loops can significantly optimize code, making it faster, cleaner, and more efficient. In the following sections, we’ll discuss the types of loops that Python offers, focusing particularly on the for loop, its syntax, and how it can be applied in real-world programming scenarios.
Types of Loops in Python
Python supports several types of loops that are used to iterate over sequences, perform repeated tasks, and manage flow control efficiently. Here, we will explore the two primary types of loops used in data science and business analytics: the for loop and the while loop.
The For Loop
The for loop in Python is used to iterate over a sequence (such as a list, tuple, dictionary, set, or string) and execute a block of code for each element in the sequence. This loop is especially useful when you know in advance how many times the loop should run or when you want to perform an action on each element of an iterable.
While Loop
Unlike the for loop, the while loop is used to execute a set of statements as long as a condition is true. It’s particularly useful when the number of iterations is not known before the loop starts. The while loop checks its condition before executing the block of code, and if the condition is true, the loop continues until the condition becomes false.
In this post, we’ll get started with for loop coding in earnest. As for the while loop, just know for now that it exists and it serves a different purpose. We’ll have a separate post discussing it next week.
How to Write For Loop Code in Python
The basic syntax of a for loop in Python is structured as follows:
for variable in sequence: # Code block to execute for each element
Where:
- Variable. Is the placeholder that temporarily holds each element from the sequence as the loop iterates. This placeholder can be named with any valid identifier.
- Sequence. Represents the collection over which the loop will iterate. This could be a list, tuple, set, string, or any iterable object.
- Code block. Contains the operations or statements that execute for each iteration of the loop.
Example of a For Loop
In practice, here’s how a simple for loop would look like in your Jupyter Notebook:
fruits = ['apple', 'banana', 'cherry'] for fruit in fruits: print(f"I like {fruit}")
As discussed previously, for loop code can be broken up into components. In this case, we have the following:
- fruits. This is the sequence. It’s a list of strings containing names of fruits.
- fruit. Not to be confused with the Fruits sequence, this is the one that comes after the for keyword in the example. Each iteration of the loop takes the next element from the fruits list and assigns it to this variable.
- print(f”I like {fruit}”): This is the code block. It executes for each element in the sequence. The f before the string starts an f-string, which is Python’s way of formatting strings. Inside the curly braces {fruit}, the current value of the variable fruit is inserted into the string, so each fruit name is dynamically included in the print statement.
Expected Output
I like apple I like banana I like cherry
Each time the loop iterates, it executes the print statement with the current fruit variable’s value, resulting in the sentences printed above.
Understanding each part of the for loop is crucial for beginners as it helps in grasping how repetitive tasks can be automated in Python, facilitating tasks such as data manipulation and batch processing. In the next section, we’ll explore the range() function, which enhances the control and functionality of for loops in many practical scenarios.
The Range Function and Loops
Range() is a built-in Python function that’s frequently used in tandem with for loops to exercise more precise control over the number and frequency of iterations that are executed on a set of variables. In a nutshell, the range() function generates a series of index numbers which can be used to tell a for loop which parts of a data range it will iterate on. For example, in the list:
Fruits = [apple, banana, cherry, mango, guava]
You can use range() to set the for loop to iterate only on the first 3 values.
Or, suppose that you want the for loop to skip iteration on every third value in the series, you can set up the range function to do that too.
The basic form of range() can take up to three arguments, making it versatile for various looping scenarios.
Syntax of range()
To understand the syntax of range() in Python, you have to recall basic indexing concepts for data structures where the first value is always 0. That’s because we’ll be using index positions to set the parameters of our range function. Basic range syntax is:
range(start, stop[, step])
Where:
- start. Is the index position represented by a number signifying where the loop will start its iterations If you neglect to encode the start of the range, it defaults to 0 which is the first value in a series. In our sample list, 0 is apple, 1 is banana, 2 is cherry and so on.
- stop. The endpoint of the sequence (exclusive). Consistent with the concepts we learned in how Python indexing works, the number assigned as the stop is the index position after the last value that you want to iterate on. Circling back to our example, you need to set the stop value at 3 if you want the loop to apply only on apple, banana and cherry. Even if mango occupies index position 3, the loop will not iterate on it since 3 is the value after 2 where the last iteration will happen.
- step. This is the difference between each number in the sequence. If omitted, it defaults to 1 which means that the iterations will not skip any values between the start and stop index positions since the difference if you subtract the two index position’s numbers is always 1. If you want the loop to skip one value between iterations, you need to set step to 2. If you want the loop to skip 2 index positions, set step to 3, and so on. That means if you want to iterate the loop only on apple, cherry and guava, the step value should be 2.
Range Function Example
Combining what we’ve learned, we can use range() to implement more complex logic to a for loop. In this example, we’ll enhance each fruit name in the list by appending the phrase ” is tasty” and collect all the modified names into a new list. This demonstrates how to use range() to iterate over indices and modify list elements.
Code and Breakdown
# Original list of fruits fruits = ['apple', 'banana', 'cherry', 'mango', 'guava']
# List to hold modified fruit names tasty_fruits = []
# Iterate over the range of indices from 0 to the length of the fruits list for i in range(len(fruits)): # Append " is tasty" to each fruit and add it to the tasty_fruits list tasty_fruits.append(fruits[i] + " is tasty")
# Print the new list with modified fruit names print(tasty_fruits)
Expected Output
['apple is tasty', 'banana is tasty', 'cherry is tasty', 'mango is tasty', 'guava is tasty']
Breakdown of the Code
- fruits = [‘apple’, ‘banana’, ‘cherry’, ‘mango’, ‘guava’]. This line defines the original list of fruits, which contains five different fruit names.
- tasty_fruits = []. Here, we initialize an empty list named tasty_fruits. This list will store the new names of the fruits after appending ” is tasty” to each one.
- for i in range(len(fruits)). This for loop starts by calling range(len(fruits)), which generates a sequence of indices from 0 to 4 (since there are 5 fruits). The loop uses these indices to access each element in the fruits list by its index.
- tasty_fruits.append(fruits[i] + ” is tasty”). Inside the loop, this line takes the fruit at the current index i, concatenates the string ” is tasty” to it, and appends the resulting string to the tasty_fruits list. The append() method is used to add the modified fruit name to the end of the tasty_fruits list.
- print(tasty_fruits). Finally, after the loop has processed all the elements in the original list, this line prints the tasty_fruits list, which now contains all the modified names.
This example shows how range() can be effectively used to perform operations on list elements and generate new lists based on existing data, demonstrating the power of combining loops with list operations in Python.
The For Loop with Numbers and Operations
In this example, we’ll work with a list of numbers and calculate the square of each number using a for loop combined with the range() function. The results will be stored in a new list, showing the practical use of loops for numerical calculations:
# Original list of numbers numbers = [1, 2, 3, 4, 5] # List to hold the squares of the numbers squares = []
# Iterate over the range of indices from 0 to the length of the numbers list for i in range(len(numbers)):   # Square the number at the current index and add it to the squares list   squares.append(numbers[i] ** 2) # Print the list of squared numbers print(squares)
Expected Output:
[1, 4, 9, 16, 25]
Code Breakdown
- numbers = [1, 2, 3, 4, 5]. This line defines a list named numbers that contains five integers. This list will be the input for our loop.
- squares = []: Here, we initialize an empty list named squares. This list will store the results of squaring each number in the numbers list.
- for i in range(len(numbers)). This for loop starts by calling range(len(numbers)), which generates a sequence of indices from 0 to 4 (since there are 5 numbers). These indices are used to access each number in the numbers list.
- squares.append(numbers[i] ** 2). Inside the loop, this line takes the number at the current index i, computes its square using the exponentiation operator **, and then appends the result to the squares list. The append() method adds the squared value to the end of the squares list.
- print(squares). After the loop has processed all elements in the original list, this line prints the squares list, which now contains the squares of the original numbers.
This example may process integers instead of strings, but the concept remains the same. The interations of the loop are determined by the parameters set by the range function. This is particularly useful when you want to loop selectively only on a subset of data in a larger dataset. It saves time, computing resources, and makes your data cleaner overall.
The For Loop and Range Working with Step
Combining the for loop with the range() function and its step parameter allows for even more precise control over iterations, particularly when you want to skip elements or iterate in steps. This is particularly useful in scenarios where not every element of a sequence needs processing or when you want to iterate in non-standard increments. For example, if you only want to process a small sample of a dataset, it can be done by setting a specific step parameter in the range function to suit your needs.
Fruit List Loop with Step Parameter
Let’s revisit the fruit list example, this time using the step parameter to print only every other fruit from the list:
# Original list of fruits fruits = ['apple', 'banana', 'cherry', 'mango', 'guava'] # Print every other fruit using step in range for i in range(0, len(fruits), 2): print(fruits[i])
Expected Output
apple cherry guava
In this example, the range() function is used with three parameters: the starting index (0), the ending index (the length of the list), and the step (2). This configuration causes the loop to increment by 2 each time, thus “skipping” every other fruit.
Code Breakdown
- range(0, len(fruits), 2). This call to range() generates indices starting at 0 up to the length of the fruits list (5), but steps by 2, so it generates the indices 0, 2, and 4.
- print(fruits[i]). In each iteration of the loop, i takes the values 0, 2, and 4, accessing ‘apple’, ‘cherry’, and ‘guava’ respectively. These fruits are then printed out.
Numerical Example with Step
Now, let’s go back to the numerical example from earlier and what it would look like if we add a step parameter. This time, we’ll focus on iterating over a predefined list of numbers to perform operations in non-standard increments, similar to our initial introduction of for loops.
Consider a scenario where we have a list of numbers and we want to print their squares, but only for every second number in the list.
# Original list of numbers numbers = [1, 2, 3, 4, 5] # Print the square of every second number from the list for i in range(0, len(numbers), 2): square = numbers[i] ** 2 print(f"The square of {numbers[i]} is {square}")
Expected Output
The square of 1 is 1 The square of 3 is 9 The square of 5 is 25
Code Breakdown
- range(0, len(numbers), 2). This function call starts at index 0, ends at the length of the numbers list (which is 5), and steps by 2. This generates indices 0, 2, and 4.
- square = numbers[i] ** 2. For each iteration, i takes the values 0, 2, and 4. The square of the number at these indices is calculated.
- print(f”The square of {numbers[i]} is {square}”). The result of the square calculation is printed in a formatted manner, showing the number and its square.
Similar to the example with the fruit name strings, the iterative squaring of every other value in the series is controlled by the range function’s step parameter.
And there you have it: an introduction to the concept of loops in programming along with a semi in-depth tutorial on how to start using the for loop along with the range function. In our next posts, we’ll explore other types of loops, their respective uses and how to code them.