*This notebook contains an excerpt from the Python Programming and Numerical Methods - A Guide for Engineers and Scientists, the content is also available at Berkeley Python Numerical Methods.*

*The copyright of the book belongs to Elsevier. We also have this interactive book online for a better learning experience. The code is released under the MIT license. If you find this content useful, please consider supporting the work on Elsevier or Amazon!*

< CHAPTER 5. Iteration | Contents | 5.2 While Loops >

# For-Loops¶

A **for-loop** is a set of instructions that is repeated, or iterated, for every value in a sequence. Sometimes for-loops are referred to as **definite loops** because they have a predefined begin and end as bounded by the sequence.

The general syntax of a for-loop block is as follows.

**CONSTRUCTION**: For-loop

```
for looping variable in sequence:
code block
```

A for-loop assigns the **looping variable** to the first element of the sequence. It executes everything in the code block. Then it assigns the looping variable to the next element of the sequence and executes the code block again. It continues until there are no more elements in the sequence to assign.

**TRY IT!** What is the sum of every integer from 1 to 3?

```
n = 0
for i in range(1, 4):
n = n + i
print(n)
```

```
6
```

**WHAT IS HAPPENING?**

First, the function

*range(1, 4)*is generating a list of numbers beginning at 1 and ending at 3. Check the description of the function*range*and get familiar with how to use it. In a very simple form, it is*range(start, stop, step)*, and the*step*is optional with 1 as the default.The variable

*n*is assigned the value 0.The variable

*i*is assigned the value 1.The variable

*n*is assigned the value*n + i*(\(0 + 1 = 1\)).The variable

*i*is assigned the value 2.The variable

*n*is assigned the value*n + i*(\(1 + 2 = 3\)).The variable

*i*is assigned the value 3.The variable

*n*is assigned the value*n + i*(\(3 + 3 = 6\)).With no more values to assign in the list, the for-loop is terminated with

*n = 6*.

We present several more examples to give you a sense of how for-loops work. Other examples of sequences that we can iterate over include the elements of a tuple, the characters in a string, and other sequential data types.

**EXAMPLE:** Print all the characters in the string `"banana"`

.

```
for c in "banana":
print(c)
```

```
b
a
n
a
n
a
```

Alternatively, you could use the index to get each character. But it is not as concise as the previous example. Recall that the length of a string could be determined by using the *len* function. And we could ignore the start by only giving one number as the stop.

```
s = "banana"
for i in range(len(s)):
print(s[i])
```

```
b
a
n
a
n
a
```

**EXAMPLE**: Given a list of integers, *a*, add all the elements of *a*.

```
s = 0
a = [2, 3, 1, 3, 3]
for i in a:
s += i # note this is equivalent to s = s + i
print(s)
```

```
12
```

The Python function *sum* has already been written to handle the previous example. However, assume you wish to add only the even numbers. What would you change to the previous for-loop block to handle this restriction?

```
s = 0
for i in range(0, len(a), 2):
s += a[i]
print(s)
```

```
6
```

**NOTE!** We use *step* as 2 in the *range* function to get the even indexes for list *a*. Also, a Python shortcut that is commonly used is the operator *+=*. In Python and many other programming languages, a statement like *i += 1* is equivalent to *i = i + 1* and same is for other operators as *-=*, **=*, */=*.

**Example** Define a dictionary and loop through all the keys and values.

```
dict_a = {"One":1, "Two":2, "Three":3}
for key in dict_a.keys():
print(key, dict_a[key])
```

```
One 1
Two 2
Three 3
```

In the above example, we first get all the keys using the method *keys*, and then use the key to get access the value. Alternatively, we could use the *item* method in a dictionary, and get the key and value at the same time as show in the following example.

```
for key, value in dict_a.items():
print(key, value)
```

```
One 1
Two 2
Three 3
```

Note that, we could assign two different looping variables at the same time. There are other cases that we could do things similarly. For example, if we have two lists with same length, and we want to loop through them, we could do as the following example using the *zip* function:

```
a = ["One", "Two", "Three"]
b = [1, 2, 3]
for i, j in zip(a, b):
print(i, j)
```

```
One 1
Two 2
Three 3
```

**EXAMPLE:** Let the function *have_digits* has the input as a string. The output *out* should take the value 1 if the string contains digits, and 0 otherwise. You could use the *isdigit* method of the string to check if the character is a digit.

```
def have_digits(s):
out = 0
# loop through the string
for c in s:
# check if the character is a digit
if c.isdigit():
out = 1
break
return out
```

```
out = have_digits('only4you')
print(out)
```

```
1
```

```
out = have_digits('only for you')
print(out)
```

```
0
```

The first step in the function *have_digits* assumes that there are no digits in the string *s* (i.e., the output is 0 or False).

Notice the new keyword *break*. If executed, the *break* keyword immediately stops the most immediate for-loop that contains it; that is, if it is contained in a nested for-loop, then it will only stop the innermost for-loop. In this particular case, the break command is executed if we ever find a digit in the string. The code will still function properly without this statement, but since the task is to find out if there are any digit in *s*, we do not have to keep looking if we find one. Similarly, if a human was given the same task for a long string of characters, that person would not continue looking for digits if he or she already found one. Break statements are used when anything happens in a for-loop that would make you want it to stop early. A less intrusive command is the keyword *continue*, which skips the remaining code in the current iteration of the for-loop, and continues on to the next element of the looping array. See the following example, that we use the keyword *continue* to skip the *print* function to print 2:

```
for i in range(5):
if i == 2:
continue
print(i)
```

```
0
1
3
4
```

**EXAMPLE:** Let the function *my_dist_2_points(xy_points, xy)*, where the input argument *xy_points* is a list of x-y coordinates of a point in Euclidean space, *xy* is a list that contain an x-y coordinate, and the output *d* is a list containing the distances from *xy* to the points contained in each row of *xy_points*.

```
import math
def my_dist_2_points(xy_points, xy):
"""
Returns an array of distances between xy and the points
contained in the rows of xy_points
author
date
"""
d = []
for xy_point in xy_points:
dist = math.sqrt(\
(xy_point[0] - xy[0])**2 + (xy_point[1] - xy[1])**2)
d.append(dist)
return d
```

```
xy_points = [[3,2], [2, 3], [2, 2]]
xy = [1, 2]
my_dist_2_points(xy_points, xy)
```

```
[2.0, 1.4142135623730951, 1.0]
```

Just like if-statements, for-loops can be nested.

**EXAMPLE:** Let *x* be a two-dimensional array, [5 6;7 8]. Use a nested for-loop to sum all the elements in *x*.

```
x = np.array([[5, 6], [7, 8]])
n, m = x.shape
s = 0
for i in range(n):
for j in range(m):
s += x[i, j]
print(s)
```

```
26
```

**WHAT IS HAPPENING?**

*s*, representing the running total sum, is set to 0.The outer for-loop begins with looping variable, i, set to 0.

Inner for-loop begins with looping variable, j, set to 0.

*s*is incremented by x[i,j] = x[0,0] = 5. So s = 5.Inner for-loop sets j = 1.

*s*is incremented by x[i,j] = x[0,1] = 6. So s = 11.Inner for-loop terminates.

Outer for-loop sets i = 1.

Inner for-loop begins with looping variable, j, set to 0.

*s*is incremented by x[i,j] = x[1,0] = 7. So s = 18.Inner for-loop sets j = 1.

*s*is incremented by x[i,j] = x[1,1] = 8. So s = 26.Inner for-loop terminates.

Outer for-loop terminates with s = 26.

**WARNING!** Although possible, do not try to change the looping variable inside of the for-loop. It will make your code very complicated and will likely result in errors.