{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# for loops\n", "\n", "In the previous section we introduced *{term}`lists `* in Python, one form of a collection of values that can be represented by a single variable. In this lesson we will learn how to use *{term}`loops `*. Loops allow parts of code to be repeated some number of times, such as iterating over all of the items in a Python list and performing a calculation on each item. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## A (bad) example\n", "\n", "Let’s consider an example using the list below:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "european_cities = [\"Helsinki\", \"Paris\", \"Barcelona\", \"Uppsala\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Suppose we want to print out the name of each city in our list. We could use the index value for each city and do the following:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Helsinki'" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "european_cities[0]" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Paris'" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "european_cities[1]" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Barcelona'" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "european_cities[2]" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Uppsala'" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "european_cities[3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But this is a bad idea. Why? Well there are two reasons.\n", "First, it does not scale nicely for long lists, and will take forever to type in.\n", "Second, it won’t work if the length of the list has fewer than 4 cities.\n", "Let's see an example with a new list." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "european_cities = [\"Riga\", \"Rome\", \"Athens\"]" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Riga'" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "european_cities[0]" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Rome'" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "european_cities[1]" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Athens'" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "european_cities[2]" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [ { "ename": "IndexError", "evalue": "list index out of range", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[10], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43meuropean_cities\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m3\u001b[39;49m\u001b[43m]\u001b[49m\n", "\u001b[0;31mIndexError\u001b[0m: list index out of range" ] } ], "source": [ "european_cities[3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Introducing the for loop\n", "\n", "We could do a much better job by using a `for` loop." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "european_cities = [\"Amsterdam\", \"Brussels\", \"Lisbon\", \"Reykjavik\"]" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Amsterdam\n", "Brussels\n", "Lisbon\n", "Reykjavik\n" ] } ], "source": [ "for city in european_cities:\n", " print(city)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Not only is this shorter, but it is also more flexible.\n", "Try printing out a different list of cities such as `['Detroit', 'Chicago', 'Denver', 'Boston', 'Portland', 'San Francisco', 'Houston', 'Orlando']`.\n", "Still works, right?" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Detroit\n", "Chicago\n", "Denver\n", "Boston\n", "Portland\n", "San Francisco\n", "Houston\n", "Orlando\n" ] } ], "source": [ "us_cities = [\n", " \"Detroit\",\n", " \"Chicago\",\n", " \"Denver\",\n", " \"Boston\",\n", " \"Portland\",\n", " \"San Francisco\",\n", " \"Houston\",\n", " \"Orlando\",\n", "]\n", "for city in us_cities:\n", " print(city)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### for loop format\n", "\n", "For loops in Python have the general form below.\n", "\n", "```python\n", "for variable in collection:\n", " do things with variable\n", "```\n", "\n", "Let's break down the code above to see some essential aspect of `for` loops:\n", "\n", "- The `variable` can be any name you like.\n", "- The statement of the `for` loop must end with a `:`\n", "- The code that should be executed as part of the loop must be indented beneath the `for` loop statement. The typical indentation is 4 spaces.\n", "- There is no additional special word needed to end the loop, you simply change the indentation back to normal.\n", "\n", "In summary, `for` loops are useful to repeat some part of the code a *finite* number of times." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Your daily for loop\n", "\n", "![_**Figure 2.3**. A cat's daily routine as an example loop. Original comic from ._](../img/2009-11-03-Cats-Eye.jpg)\n", "\n", "_**Figure 2.3**. A cat's daily routine as an example loop. Original comic from ._\n", "\n", "Like many other programming concepts, the idea of looping through actions is something that is already perhaps more familiar to you than you think. Consider your actions during a given day. Many people have certain routines they follow each day, such as waking up, taking a shower, eating breakfast and brushing their teeth. In Python code, we might represent such actions as follows:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```python\n", "for day in my_life:\n", " wake_up()\n", " take_shower()\n", " eat_breakfast()\n", " brush_teeth()\n", " ...\n", "```\n", " \n", "Note that `my_life` would be a list of the days of your life, and the actions you take are represented as functions, such as `wake_up()`.\n", "Furthermore, by following this kind of list of repeating actions we're able to start the day effectively even before the first cup of coffee :)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### for loop variables\n", "\n", "Note that the variable used in a `for` loop is just a normal variable and still exists after the loop has completed with the final value given to letter. Let's loop over a list of weather conditions and print them to the screen. " ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "weather_conditions = [\n", " \"rain\",\n", " \"sleet\",\n", " \"snow\",\n", " \"freezing fog\",\n", " \"sunny\",\n", " \"cloudy\",\n", " \"ice pellets\",\n", "]" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "rain\n", "sleet\n", "snow\n", "freezing fog\n", "sunny\n", "cloudy\n", "ice pellets\n" ] } ], "source": [ "for weather in weather_conditions:\n", " print(weather)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What is its value of `weather` after the `for` loop has completed?" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "After the loop, weather is ice pellets\n" ] } ], "source": [ "print(\"After the loop, weather is\", weather)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## For loops using the range function\n", "\n", "A loop can be used to iterate over any list of values in Python.\n", "So far we have considered only lists, but we could also write a loop that performs a calculation a specified number of times by using the `range()` function. Let's consider an example where we use a for loop with `value` as the loop variable and `range(5)` as the collection. Let's see what happens if we print `value` at each iteration." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n", "4\n" ] } ], "source": [ "for value in range(5):\n", " print(value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this case, we use a special function called `range()` to give us a list of 5 numbers `[0, 1, 2, 3, 4]` and then we print each number in the list to the screen.\n", "When given an integer (whole number) as an argument, `range()` will produce a list of numbers with a length equal to the specified `number`.\n", "The list starts at `0` and ends with `number - 1`.\n", "You can learn a bit more about range by typing `help(range)`.\n", "\n", "```python\n", "In [1]: help(range)\n", "```\n", "\n", "```\n", "Help on class range in module builtins:\n", "\n", "class range(object)\n", " | range(stop) -> range object\n", " | range(start, stop[, step]) -> range object\n", " | \n", " | Return an object that produces a sequence of integers from start (inclusive)\n", " | to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.\n", "... (output truncated)\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Question 2.4\n", "\n", "The program below will print numbers to the screen using the `range()` function.\n", "\n", "```python\n", "for i in range(...):\n", " print(i)\n", "```\n", "\n", "Using the documentation that is produced when you run `help(range)`, what values would you replace the `...` in the parentheses of the `range()` function with to have the following output printed to the screen? Try to first think about the function without running any code.\n", "\n", "```python\n", "2\n", "5\n", "8\n", "```" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "tags": [ "remove_cell" ] }, "outputs": [], "source": [ "# You can use this cell to enter your solution." ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "tags": [ "hide-cell", "remove_book_cell" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2\n", "5\n", "8\n" ] } ], "source": [ "# Solution\n", "\n", "for i in range(2, 9, 3):\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Looping over lists using index values\n", "\n", "Since we already know how to find the length of a list using the `len()` function, we can now take advantage of this knowledge to make our `for` loops more flexible. Let's use the `range()` function to loop over a list of numbers and add the value of the loop variable `i` to each value. In addition, we can add a few print statements to display the values of `i` and `numbers[i]` within the loop. Let's also check the updated values in the list after the loop." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "numbers = [5, 6, 7, 8]" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Value of i: 0\n", "Value of numbers[i] before addition: 5\n", "Value of numbers[i] after addition: 5\n", "\n", "Value of i: 1\n", "Value of numbers[i] before addition: 6\n", "Value of numbers[i] after addition: 7\n", "\n", "Value of i: 2\n", "Value of numbers[i] before addition: 7\n", "Value of numbers[i] after addition: 9\n", "\n", "Value of i: 3\n", "Value of numbers[i] before addition: 8\n", "Value of numbers[i] after addition: 11\n", "\n" ] } ], "source": [ "for i in range(len(numbers)):\n", " print(\"Value of i:\", i)\n", " print(\"Value of numbers[i] before addition:\", numbers[i])\n", " numbers[i] = numbers[i] + i\n", " print(\"Value of numbers[i] after addition:\", numbers[i])\n", " print(\"\")" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[5, 7, 9, 11]" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "numbers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are several important things to observe in this `for` loop:\n", "\n", "1. Because we are using the `range()` function, the value assigned to the loop variable `i` starts with `0` and increases by `1` each time through the loop. \n", "2. Value in the list `numbers` at index `i` increases at each iteration. \n", "3. The value that changes in the list `numbers` in each iteration through this for loop is the value at index `i`, while the other values are not updated. This occurs because we're assigning a new value at `numbers[i]`.\n", "4. Value of `numbers[i]` on the right side of the equation is the \"old\" value. That \"old\" value is increased by `i` first, and then stored as the updated value `numbers[i]`.\n", "\n", "The variable `i` is commonly used to denote the index variable in loops. Loops can sometimes occur with another loop (referred to as nested loops), in which case other index variables such as `j` or `k` may be used." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Why use index value to loop over a list?\n", "\n", "Good question. First off, if you want to update individual values in a list you're likely going to need to loop that includes the index values. There are functions such as `enumerate()` that can help, but their use can be somewhat confusing for new programmers. Second, in cases where you have multiple lists that are related to one another, it can be handy to use a loop with the index values to be able to access corresponding locations in each list. For this, let's consider an example with two lists." ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "cities = [\"Helsinki\", \"Stockholm\", \"Oslo\", \"Reykjavik\", \"Copenhagen\"]" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "countries = [\"Finland\", \"Sweden\", \"Norway\", \"Iceland\", \"Denmark\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As you can see we have 5 cities and 5 corresponding counties. Let's print out each pair using a single for loop." ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Helsinki is the capital of Finland\n", "Stockholm is the capital of Sweden\n", "Oslo is the capital of Norway\n", "Reykjavik is the capital of Iceland\n", "Copenhagen is the capital of Denmark\n" ] } ], "source": [ "for i in range(len(cities)):\n", " print(cities[i], \"is the capital of\", countries[i])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Cool. So as you can see, the index `i` is used in this case to access each item in the two lists of cities and countries and allow us to print out the city/country pairs. We'll get more practice with this kind of thing in the exercises for this week. In the example above, we used the length of the list `cities` in the `range()` function. We could just as easily used the list `countries` to define the values of `i` since both lists are the same length." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Question 2.5\n", "\n", "What output would the following program produce? Try to first think about the loop without running any code.\n", "\n", "```python\n", "odd_numbers = [1, 3, 5, 7, 9]\n", "even_numbers = [10, 4, 6, 8, 2]\n", "for i in range(len(odd_numbers)):\n", " print(odd_numbers[i] + even_numbers[i])\n", "```" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "tags": [ "remove_cell" ] }, "outputs": [], "source": [ "# Use this cell to enter your solution." ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "tags": [ "hide-cell", "remove_book_cell" ] }, "outputs": [ { "data": { "text/plain": [ "11" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Solution\n", "\n", "11\n", "7\n", "11\n", "15\n", "11" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Footnotes" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.9" } }, "nbformat": 4, "nbformat_minor": 4 }