Beginner: For and While Loops
Welcome to the Week 3 Beginner Python Notebook. This notebook is designed for students who are just starting out with the Python programming language.
Your task today is to read through the material carefully and complete the exercises provided at the end. These exercises are an important part of the learning process and will help you check your understanding.
Important: You have three options for today’s work:
Beginner,Intermediate, orAdvanced. If you are new to Python, please choose this Beginner notebook. You will have plenty of opportunities later in the course to explore the other levels.
In this notebook, you will be introduced to loops. In particular, you will learn what an iterator, iterable, for loop and while loop are. Loops are fundamental to coding as they allow you to automatically repeat computations on a large scale.
Be sure to work through the examples and attempt all the exercises. They are designed to reinforce your learning and build your confidence.
Table of Contents
Motivation
Over the past two weeks, we have looked at some basic data types and conditional logic in Python. This week it is time to start scaling up our computation!
To begin today, let’s consider a simple coding task. Suppose you are asked to print the first 10 Triangle Numbers. With only what we know so far, the code might look something like this:
This code is already long and repetitive, but imagine if I’d instead asked you to go up to \(100\), or \(1,000\)! This task would be impossible!
Loops give us a way to automate repetition. Instead of writing the same line of code again and again, we’ll learn how to tell Python: “Do this thing repeatedly until I say stop.”
By the end of today, you’ll be able to write the same task in just one or two lines of code.
Iterators and Iterables
So far we’ve seen several basic data types in Python:
- Numeric data types:
3,-10,4.5 - Strings:
"hello","Python" - Booleans:
True,False
But often, we want to work with more than one piece of data at once. For example: a list of students in a class, a list of prices in a shop, or a list of daily temperatures.
In Python, a list is a collection of values, written inside square brackets []:
In the same way that floats, ints, strings and booleans are data types in Python, so is a list. For example:
A list can contain as many elements as you want, and they don’t all have to be the same type.
You can also ask for one item at a time using its index (position in the list). Python uses zero-indexing, which means it starts counting from 0:
A list is an example of an iterable object.
An iterable object is any Python object that contains a countable number of elements; in other words, it’s an object that can give you it’s elements one by one.
We’ve already seen two examples of iterables:
lists are iterables:[10,20,30,40]can give you10,20,30,40.strings are also iterables:"hello"can give you"h","e","l","l","o".
Given an iterable object, you can create something known as an iterator.
An iterator is a special object that lets you step through the elements of an iterable, one at a time, and remembers where you are in the process. In Python, you can create an iterator from an iterable using the built-in function iter():
The useful thing about an iterator is that it lets us print elements out one by one, always remembering where we were up to. Specifically, we can use the built-in next function to get each element in turn:
A particularly useful example of an iterable object is the output of the range function. You can think of range(n) as a compact way of representing the numbers 0, 1, 2, ..., n-1. In other words, it produces an iterable containing the first n non-negative integers, ready to be used in computations.
Test your understanding: By modifying the above code, work out what happens if you give
rangetwo inputs instead of one. e.g. what doesrange(2,4)do?
Recap: In this section, we introduced a new data type, the list, and saw that lists (as well as strings) are examples of iterables. We also learned about iterators, which are the tools Python uses to step through those iterables one element at a time.
To summarize, here are the definitions of iterable and iterator:
Iterable: an object that multiple elements (like alistorstring) that can be listed off one at a time.Iterator: an object that remembers a position within an iterable and produces the next element each time you ask for it.
In the next section, we will see how you can move through values of an iterable object automatically using a for loop.
Note: If you would like to learn more about
lists, have a look at the week 1 intermediate notebook oncollections. This will show you various operations that can be performed on lists, as well as introduce you to other iterable data types such as tuples, sets and dictionaries.
for loops
In the last section, we saw how an iterator can give us the elements of an iterable one at a time using the next() function. But having to write next() repeatedly is a bit repetitive and clunky…
Python gives us a much simpler way to go through all the elements of an iterable: the for loop.
In this code:
numbersis the iterable.numis a variable that takes on the value of each element, one at a time.
The indented block of code under the loop (print(num)) runs once for each element.
Let’s break down the general syntax of the for loop. The first line must contain the for keyword and a colon, :. These tell us where the for loop starts.
`for` keyword colon
↓ ↓
for my_variable in my_iterable:
print("My variable now equals", my_variable)
Then, after the for, we must name a variable. Here my_variable is just a name you are choosing to represent an arbitrary element in the iterable object. >
> variable name
> ↓
> for my_variable in my_iterable:
> print("My variable now equals", my_variable)
>
After the variable is named we write the the in keyword followed by my_iterable. Here my_iterable is the iterable variable you want to loop through (for instance, a list or string) and the in keyword tells us that we are looking at values in that iterable. >
> `in` keyword iterable object
> ↓ ↓
> for my_variable in my_iterable:
> print("My variable now equals", my_variable)
>
Finally, inside the loop, we provide the code we want to run for every value of my_variable. In this case we are just printing it’s value.
for my_variable in my_iterable:
print("My variable now equals", my_variable) ← body of the for loop
Let’s see some examples.
Test your understanding: Make sure you understand this last example. How would you modify it to print the length of each word in the sentence? Hint: You might need the
len()function from the week 1 beginner notebook.
Warning: Just like with an if statement, the body of a for loop must be indented. If you forget to indent, or if the indentation is inconsistent, Python will raise an error.
while loops
A for loop is useful when we want to repeat a computation once for every element in an iterable. But sometimes, instead of looping over a collection, we want to keep running a computation until a certain condition is met.
For example, we might want to:
- keep rolling a die (generating random integers between \(1\) and \(6\)) until we get a six, or
- keep doubling a value until it becomes larger than 100.
To handle situations like these, Python provides the while loop.
A while loop repeatedly runs a block of code so long as a given Boolean statement is True. For example, in the below, the block of code is run while the statement n < 10 is True.
The syntax for a while loop looks very similar to an if statement. A while loop is introduced using the keyword while and a colon ::
while keyword colon
↓ ↓
while my_boolean:
# Run some code
In-between these, we must include a booean statement, e.g. my_boolean.
Boolean statement
↓
while my_boolean:
# Run some code
Finally, the indented lines underneath form the body of the loop. This is the part that runs repeatedly:
while my_boolean:
# Run some code ← body of the while loop
The body will keep running again and again as long as the boolean expression evaluates to True. It is worth making the comparison between if statements and while loops explicit:
- An
ifstatement checks its condition once and runs the body a single time (ifTrue). - A
whileloop keeps checking the condition and repeats the body until the condition becomesFalse.
Let’s look at a small worked example to make the while loop syntax clearer.
In this example, we can imagine the while loop as if Python were repeating the indented code over and over:
After every repetition, the loop is checking whether the boolean i < 3 is True. Since, on the last repetition i is now equal to 3, the condition is False, so the loop does not run another time. That is, the while loop ends there.
Warning: A
whileloop will keep running as long as its boolean condition isTrue. If the condition never becomesFalse, the loop will never end. This is called an infinite loop.For example, the following code never terminates because
iis never updated (run this at your peril!):
To avoid infinite loops, you must ensure that the boolean eventaully becomes
False.Of course, mistakes are inevitable. In a Jupyter notebook, an infinite loop can freeze the cell. If this happens, do one of the following:
- Click the
"stop"button (■) in the toolbar, or- Use the menu:
Kernel -> Interrupt.- Use the menu:
Kernel -> Restart.The last option completely restarts the Python notebook and clears everything from memory, so use it only as a last resort.
Nested Loops
One of the most useful features of loops is that you can nest them inside one another.
That means you can put a for loop inside a while loop, a while loop inside a for loop, or even nest loops of the same kind. This is powerful as it lets us perform tasks that require multiple layers of repetition. Here are some examples:
Test your understanding: If you have already run the three code boxes above, clear the output from each. On paper, use your understanding of loops to predict exactly what each example will
To see why nested loops are useful, let’s work through an example.
Suppose we want to list all prime numbers up to a given number n.
Intuitively we need to check whether each number between \(1\) and \(n\) is prime. We can visualise this like so:
But how do we do the check inside the loop? Well, let’s take an example value of i, say i = 7. If we were doing this task by hand, we’d check if 7 is divisible by 2, then by 3, then by 4, and so on until we reach 7. This can be done with a loop too:
Test your understanding: Why does the above code work? If you are unsure, ask one of the demonstrators for help!
This code tells us if one value (here i=7) is prime. But, how can we relate this to our original problem, checking if all values between 1 and n are prime? The answer is simply that we can place this code inside our larger loop from earlier:
Exercises
Question 1: Given the two strings in the code block below, use a while loop and the split function to make a new string which contains: - the 1st word from the 1st string - the 1st word from the 2nd string - the 2nd word from the 1st string - the 2nd word from the 2nd string - the 3rd word from the 1st string - … and so on
Each word must be seperated from the last with a space.
Hint: You may wish to look up the split function in the Week 1 beginner notebook.
Question 2: By looking up the documentation for the range function. Write some code which prints the numbers 1 to 100 in reverse order. That is, 100 should be printed first, then 99 and so on…
Question 3: Below is an integer n. Using a while loop, compute the factorial of \(n\) given by \(n!=n\times (n-1)\times... \times 2 \times 1\).
Question 4: Using a for loop, print the square of all of the elements in the list below which are greater than \(2\) or less than \(-2.5\).
Now do the same, but saving the elements in a new list named output_list.
Hint: You can add a new element to a list by using the append method. An example of this is given in the below code block.
Question 5: Without running the below code, predict how many times the word "Python" will be printed. Explain your answer, and then verify it by running the below code.
Question 6: The below code uses a while loop to count the number of vowels in the word word. However, something has gone wrong! The below code will never terminate when run. Explain why this has happened and implement a fix.
Note: Be careful running this code! As mentioned above, in it’s current form, the code will never terminate.
Question 7: Using a loop, work through the dictionary of exam results below to find the difference between the highest and lowest scores. Print the names of the students who achieved those scores. You may assume that all scores like between \(0\) and \(100\).
Note: In this question, we are using the dictionary datatype. Dictionaries in Python allow us to store data as key-value pairs. In this case, the key is a student’s name, and the value is their exam score. For this question, you need to know that you can access individual items like
print(exam_results['Liam Turner'])and you can obtain a list of all the keys (student names) usingnames_in_dict = exam_results.keys(). If you would like to learn more about the dictionary datatype, please have a look at the week 1 intermediate notebook.
Question 8: Use two nested for loops to print the first n lines of Pascal’s Triangle. For instance, if \(n=5\) your code should print:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
Question 9: A palendromic number is an integer that reads the same when its digits are reversed.
For example:
- \(124\) is not palindromic, because reversing the digits gives \(421\neq 124\).
- \(121\) is palindromic, because reversing the digits gives \(121=121\).
Using the range function together with a for loop, compute all palindromic numbers between \(0\) and \(1000\).
Hint: You can reverse a string using [::-1] as shown below:
This is an example of slicing. If you would like to learn more about slicing lists see the Week 1 (Intermediate) notebook.
Question 10: Using a while loop and a for loop, compute the smallest positive number that is evenly divisible by all of the numbers from \(1\) to \(8\).
Hint: These loops may need to be nested inside one another!