Intermediate Python

The zip function provides a way to loop over more that one list at once. It takes two arguments, each of which should be a list and gives you back something you can loop over.

For example, imagine we have the two lists a and b:

In [1]:
a = [1, 2, 3, 4]
b = [5, 6, 7, 8]

we can pass them to the zip function and have a look at what it returns:

In [2]:
zip(a, b)
Out[2]:
<zip at 0x7ff49c451300>

hmm, this doesn't look very useful, it's just returned us a zip?

In fact, it has given us back a zip object. This is an object which, when looped over, will give us the elements one at a time. The reason it is done like this is that it means that it only has to calculate the elements as it goes along rather than doing them all up-front. This is termed a lazy iterator and is something which crops up often in Python.

To force it to give us all the elemnts at once, we can turn it into a list by using the list function:

In [3]:
list(zip(a, b))
Out[3]:
[(1, 5), (2, 6), (3, 7), (4, 8)]

That looks more useful! It is a list where each element is a pair of values. The first element is the pair 1, 5. This has come from the first element in a (1) and the first element in b (5).

The second element in the list is 2, 6 which has come from the second element in each input list.

We can see this in a slightly different way by looping over the result of the zip rather than passing it to the list function:

In [4]:
for element in zip(a, b):
    print(element)
(1, 5)
(2, 6)
(3, 7)
(4, 8)

Again we see that the pairs have been printed out, taken from each input list.

We can break the element into its parts using indexing notation:

In [5]:
for element in zip(a, b):
    print(f"from a: {element[0]}, from b: {element[1]}")
from a: 1, from b: 5
from a: 2, from b: 6
from a: 3, from b: 7
from a: 4, from b: 8

The downside of this is that we have to remember that element[0] refers to a. Instead, we can break the pair apart directly in the for loop by providing a name for each part:

In [6]:
for from_a, from_b in zip(a, b):
    print(f"from a: {from_a}, from b: {from_b}")
from a: 1, from b: 5
from a: 2, from b: 6
from a: 3, from b: 7
from a: 4, from b: 8

That should give you enough understanding of the zip fucntion to follow what our array-adding code is doing.