Search for Courses, Topics
certificate icon
Certificate

Learn on Scaler Topics and get certified.

static-certificate

Zip in Python | Zip Function in Python

Learn about Zip Function in Python.

21 Dec 2021-12 mins read
quiz
Challenge Inside! : Find out where you stand! Try quiz, solve problems & win rewards!

Overview

The zip() function in python is an in-built function that takes any number of iterables(list, str, etc.) as an argument and aggregate them together by taking elements from each iterable passed as argument.

It stops when the shortest iterable is exhausted and the elements in longer iterables are left out. It is mostly used to iterate through multiple iterables.

Syntax of zip() function in Python

The syntax of zip() function is as follows,

zip(*iterables)

The * means that zip can take a variable number of iterables as arguments. Thus, zip(*iterables) means zip(iterable1, iterable2, iterable3, ...).

Parameters of zip() function in Python

Any number of built-in (list, dict, string) or user-defined iterables.

Return value of zip() function in Python

Return Type: <class 'zip'>

The zip function returns a zip object which is an iterator of tuples with values derived from the iterables passed as arguments.

Example of zip() function in Python

countries = ["India", "UK", "USA", "Canada"]
capitals = ["Delhi", "London", "Washington DC", "Ottawa"]

country_capital = zip(countries, capitals)

print(country_capital)
print(list(country_capital))

Output:

<zip object at 0x7fce6586fb40>
[('India', 'Delhi'), ('UK', 'London'), ('USA', 'Washington DC'), ('Canada', 'Ottawa')]

Explanation:

Let's go through the code line by line:

  • We first created two lists: countries and capitals.
  • As you can see, the ith city is the capital of ith country.
    • For example, the 0th element of capitals (Delhi) is the capital city of the 0th element of the countries (India).
  • Then, we passed both the lists to the zip function to combine them into a single list of tuples of the format (country, capital).
  • The zip function returns an iterator of tuples which we stored in the variable country_capital.
  • We need to convert the zip object into a list to print on the console.

What is zip() function in Python?

Very often, in programming, we need to loop through multiple sequences together.

For instance, if you have two lists:

  • countries: list of names of the countries.
  • capitals: list of capital cities of those countries.

Now, you need to iterate over both lists and print the following line for each combination: capital of {country} is {capital}.

Python provides the zip function for this exact purpose.

Zip is an in-built function in Python used to iterate over multiple iterables.

It takes corresponding elements from all the iterable passed to it and merges them in a tuple.

Note: Tuples are immutable data structures defined with parenthesis that store an ordered sequence of values. For example: (1, 2, 3) is a tuple with three values. As tuples are immutable, you can not change the values inside them after it is defined.

The following figure illustrates the same:

  • The zip function took a list of countries and a list of capitals.
  • Then merged their corresponding elements in a tuple.
  • That means the ith tuple has ith elements from both the list.
    illustration of python zip function

To understand zip() function, you must know:

  • An iterable is an object of a series of elements that can be iterated. For example, a list is an iterable:
    l = [1, 2, 3, 4, 5, 6]
    
  • An iterator is an object used to iterate over an iterable.
    • We can generate an iterator object using the iter method on an iterable.
    • Use the next function to get a value from an iterable using an iterator.
    Example:
    l = [1, 2, 3, 4, 5, 6]
    
    iterator = iter(l)    # Creating an iterator
    print(next(iterator)) # Getting value from iterable
    print(next(iterator)) 
    
    Output:
    1
    2
    
    • Note: An iterator object exhaust and raise the StopIteration error once all the values underneath the iterable are read.
    • Fun Fact: When you are using a for loop to iterate over a list, it is using an iterator underneath to perform the looping.

In the following sections, you will learn how to use the zip function to loop through multiple iterables, how it works, and several examples to make things clear.

How Python's zip() Function works

Let's understand the internal working of the zip function:

  • The zip function first calculates the number of iterables passed as argument.
  • Then, it calculates the minimum common length of all iterables. Let's call this num_items.
  • Then, it creates a new list of length num_items, which will contain tuples consisting of elements from all the iterables passed to the zip function. Let's call it return_list.
  • Then, the zip function creates an iterator for each iterables passed to it.
  • After that, the zip function iterate over return_list and in each position i, add the elements from the ith position of all of iterables passed to zip function. This is done by using the iterators created in the previous step.
  • Finally, the return_list is returned.
  • Note: The zip function also performs some checks for edge cases and data types.

How the zip() Function creates an iterator of Tuples?

The zip function creates an iterator of tuple by taking elements from each iterable passed as argument and aggregating them together:

zip(a, b) = [(a0, b0), (a1, b1), (a2, b2), ...]

It stops when the shortest iterable is exhausted, and the elements in longer iterables are left out.

More Examples

Let's review some examples of how to use zip functions for a better understanding.

Example 1: Using Python zip() function with two lists

Let's start with the most simple one, zipping two lists of the same length:

numbers = [1, 2, 3, 4, 5]
square = [1, 4, 9, 16, 25]

num_square = zip(numbers, square)

print(list(num_square))

Output:

[(1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]

Explanation:

Both numbers and square are of the same length. Therefore the zipped list num_square is also of the same length 5. Thus, Corresponding elements are merged in a tuple of size 2, and no element is left out.

Example 2: No iterable Passed to Zip Function

What if we pass no iterable to the zip function? Let's try it out:

empty_zipped = zip()

print(list(empty_zipped))

Output:

[]

Explanation:

The zip function returns an empty iterator when no iterable is passed, thus, it is converted into an empty list.

Example 3: One Iterable Passed to Zip Function

Let's see what is the output when we pass only one iterable to the zip function:

countries = ["India", "UK", "USA", "Canada"]
single_zipped = zip(countries)

print(list(single_zipped))

Output:

[('India',), ('UK',), ('USA',), ('Canada',)]

Explanation:

Because only one iterable is passed, the zip function returned an iterator of tuples with length 1. Therefore, the Output is a list with tuples of size 1 where each element is taken from the single iterable countries.

Example 4: Multiple iterables Passed to Zip Function

Till now, we have only passed one or two iterables to the zip function, but there is no limit to that. Let's try passing three iterables now:

countries = ["India", "UK", "USA", "Canada"]
capitals = ["Delhi", "London", "Washington DC", "Ottawa"]
dial_code = ["+91", "+44", "+1", "+1"]

country_capital = zip(countries, capitals, dial_code)

print(list(country_capital))

Output:

[('India', 'Delhi', '+91'), ('UK', 'London', '+44'), ('USA', 'Washington DC', '+1'), ('Canada', 'Ottawa', '+1')]

Explanation:

Now we have 3 iterables - countries, capitals, dial_code with 4 elements each. Thus, the zipped list will have 4 tuples of size 3 each.

Example 5: Iterables of different length

What if one iterable has fewer elements than the others?

countries = ["India", "UK", "USA", "Canada"]
capitals = ["Delhi", "London"]

country_capital = zip(countries, capitals)

print(list(country_capital))

Output:

[('India', 'Delhi'), ('UK', 'London')]

Explanation:

The zip function returned an iterator of two tuples because the iterator stops when the shortest iterable is exhausted and the elements in longer iterables are left out. In this case, the capitals iterable which has two elements is exhausted before the countries iterable. Therefore the zipped list has all the elements from capitals but the last 2 elements of countries - USA and Canada are left out.

Example 6: Usage of zip_longest()

If you want to zip all elements even when the shortest iterable is exhausted, you can use the zip_longest function from the itertools library:

from itertools import zip_longest

countries = ["India", "UK", "USA", "Canada"]
capitals = ["Delhi", "London"]

country_capital = zip_longest(countries, capitals)

print(list(country_capital))

Output:

[('India', 'Delhi'), ('UK', 'London'), ('USA', None), ('Canada', None)]

Explanation:

zip_longest merges elements from each of the iterables. If the iterables are of uneven length, missing values are filled in with the default value of None. Iteration continues until the longest iterable is exhausted.

We can provide another default value using the fillvalue parameter:

from itertools import zip_longest

countries = ["India", "UK", "USA", "Canada"]
capitals = ["Delhi", "London"]

country_capital = zip_longest(countries, capitals, fillvalue="Capital Missing")

print(list(country_capital))

Output:

[('India', 'Delhi'), ('UK', 'London'), ('USA', 'Capital Missing'), ('Canada', 'Capital Missing')]

Example 7: Unzipping the values using zip()

There is no special function to unzip zipped iterables, you can use the zip function with the * operator to unzip a zip object:

countries = ["India", "UK", "USA", "Canada"]
capitals = ["Delhi", "London", "Washington DC", "Ottawa"]

# Zip countries & capitals together
country_capital = list(zip(countries, capitals))

print(country_capital)

# Unzip country_capitals into separate iterables
countries_unzipped, capitals_unzipped = zip(*country_capital)

print(countries_unzipped)
print(capitals_unzipped)

Output:

[('India', 'Delhi'), ('UK', 'London'), ('USA', 'Washington DC'), ('Canada', 'Ottawa')]
('India', 'UK', 'USA', 'Canada')
('Delhi', 'London', 'Washington DC', 'Ottawa')

Explanation:

The * operator is the unpacking operator, it unpacked the country_capital list into separate tuples. so writing zip(*country_capital) was equivalent to:

zip(('India', 'Delhi'), ('UK', 'London'), ('USA', 'Washington DC'), ('Canada', 'Ottawa'))

These tuples acted as iterables to be zipped again. Thus giving an iterator of two tuples as Output with 4 members each.

Example 8: Converting Zip Object into a Dictionary

A zip object with a tuple of size 2 can be converted to a dictionary:

countries = ["India", "UK", "USA", "Canada"]
capitals = ["Delhi", "London", "Washington DC", "Ottawa"]

country_capital = zip(countries, capitals)

country_capital_dict = dict(country_capital)
print(country_capital_dict)

Output:

{'India': 'Delhi', 'UK': 'London', 'USA': 'Washington DC', 'Canada': 'Ottawa'}

Explanation:

It is possible because the dict function accepts an iterable of tuples for dictionary creation.

A tuple of size two provides a (key, value) pair for the dictionary.

Example 9: Using Zip Object in a Loop

As a zip object is an iterator, it can be traversed with the next function until the StopIteration exception is reached.

countries = ["India", "UK", "USA", "Canada"]
capitals = ["Delhi", "London", "Washington DC", "Ottawa"]

country_capital = zip(countries, capitals)

while True:
  try:
    country, capital = next(country_capital)
    print("Capital of", country, "is", capital)
  except StopIteration:
    break

Output:

Capital of India is Delhi
Capital of UK is London
Capital of USA is Washington DC
Capital of Canada is Ottawa

Explanation:

The next function is provided by any iterator for traversal and once the iterator is exhausted, a StopIteration Exception is raised. We can use these two together for traversing a zip object with a while loop.

Note: In the next section, you will find a more convenient way to loop through a zip object.

Example 10: Looping Over Multiple Iterables Using Zip Function in Python

You can loop through a single iterable using a for loop:

countries = ["India", "UK", "USA", "Canada"]

for country in countries:
  print(country)

But what if you need to loop over multiple iterables? You may use the range function to do this:

countries = ["India", "UK", "USA", "Canada"]
capitals = ["Delhi", "London", "Washington DC", "Ottawa"]

for index in range(len(countries)):
  print("Capital of", countries[index], "is", capitals[index])

Explanation:

In this method, we are using the range method to loop through numbers from 0 to the length of a list and inside the loop, we are using that number as an index for accessing values from the list.

But this method is not the best option available to us. First, it is not very readable. Second, it may cause IndexError if we used the shorter list inside the len function.

The better choice would be to use the zip function as below:

countries = ["India", "UK", "USA", "Canada"]
capitals = ["Delhi", "London", "Washington DC", "Ottawa"]

for country, capital in zip(countries, capitals):
  print("Capital of", country, "is", capital)

Output:

Capital of India is Delhi
Capital of UK is London
Capital of USA is Washington DC
Capital of Canada is Ottawa

Explanation:

We are using the zip function to create an iterator of tuple with corresponding values from both the iterable and then unpacking them into separate variables: country & capital.

Example 11: Real-Life Application of Zip Function

The zip function can be used for quick calculations. Suppose you have the following data about three stocks you owned:

Price/StockStock 1Stock 2Stock 3
Buy Price507030
Sell Price8065120

Now you need to calculate your net profit. You can use the zip function as follows to do it quickly:

buy_prices = [50, 70, 30]
sell_prices = [80, 65, 120]

profit = 0
for buy_price, sell_price in zip(buy_prices, sell_prices):
  profit += sell_price - buy_price

print("Your net profit is", profit)

Output:

Your net profit is 115

Explanation:

We created two lists for buy price and sell price. Then assigned the profit to 0 initially. We used the zip function to iterator over both lists easily in the for loop and calculated profit by subtracting sell price and buy price and then adding that value to the previous value of profit using the += operator. Finally, we printed the net profit.

Conclusion

  • Zip is a useful in-built function provided by Python to loop through multiple iterables.
  • Zip takes any number of iterables and returns a zip object which is an iterator of tuples.
  • Each ith tuple inside the zip object has ith element from each iterable.
  • Zip returns an empty iterator when no argument is passed.
  • Zip returns an iterator of a single value tuple when a single argument is passed.
  • When n number of iterables are passed, each tuple has n number of elements.
  • When passed iterables have different lengths, the returned iterator has the length of the shortest iterable.
  • We can use the zip_longest function to zip all elements of all iterables.
  • We can unzip a zip object using the * operator and zip function.
  • A zip object can be converted to a dict.
  • We can use a zip object in a while loop with the next function and StopIteration exception.
  • We can loop through multiple iterables conveniently using the zip function.
  • We need to convert a zip object into a list to use it multiple times or to print it onto the console.
Challenge Time!
quiz Time to test your skills and win rewards! Note: Rewards will be credited after the next product update.