Python: lists to tuples and tuples to lists

Get the code for this example
The zip function in Python accepts a number of sequences (such as lists or arrays) and returns a list of tuples.  The first element of each tuple comes from the first sequence, the second from the second sequence, and so on.  For example:

a = range(0, 5)
b = range(5, 10)
c = range(10, 15)
sequence_of_tuples = zip(a, b, c)
print(sequence_of_tuples)
[(0, 5, 10), (1, 6, 11), (2, 7, 12), (3, 8, 13), (4, 9, 14)]

I often use zip when I have a list of x coordinates and a list of y coordinates, and I need to pass a list of (x,y) pairs to a function.
The question is: what is the opposite of zip? How do you convert a sequence of tuples to multiple sequences? It turns out that zip is its own inverse, due to an obscure feature of the Python language called arbitrary argument lists.

a1, b1, c1 = zip(*sequence_of_tuples)
print(a1)
print(b1)
print(c1)

Why does this work?  The * in front of an argument to a function causes Python to unpack a list or tuple and pass the results as arguments to the function.  Let’s see what arguments are actually being passed to zip:

def test_fn(*args):
    """Number of arguments is not known in advance"""
    print("Arguments passed to function:")
    for a in args:
        print a
test_fn(*sequence_of_tuples)

In our example, five tuples are passed to the function.  zip returns a list of tuples, where each tuple contains the i-th element from each of the argument sequences.  Thus, the sequence of tuples is converted back to separate sequences.  If you want lists instead of tuples, simply use list to convert the tuple to a list:

a1 = list(a1)

For a thorough discussion on the “opposite of zip”, see this thread.

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.