In Python you can `zip`

two iterables together.

```
i1 = 'abcde'
i2 = [1, 2, 3, 4, 5]
zipped = zip(i1, i2)
```

This `zipped`

variable points to a new iterable that contains tuples of `i1`

/`i2`

contents.

```
print(list(zipped))
# [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
```

This is all relatively straightforward, but how can you now go the other way around?

## Reverse `zip`

Suppose now that we have a list of tuples. How might we turn this list of tuples into two iterables that split the integers from the characters?

```
tuples = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
```

It turns out that you can use `zip`

again!

```
l1, l2 = zip(*tuples)
print(l1)
# ('a', 'b', 'c', 'd', 'e')
print(l2)
# (1, 2, 3, 4, 5)]
```

## How does this work?

You may be suprised by this. How does a function for zipping also handle the unzipping?

Let's begin by understanding what `zip()`

does when we pass it two lists with two items each.

```
print(list(zip(['a', 1], ['b', 2])))
# [('a', 'b'), (1, 2)]
```

It seems we're creating two tuples as output. One contains all the items at index 0. The other contains items at index 1.

So what would happen when we add another list?

```
print(list(zip(['a', 1], ['b', 2], ['c', 3])))
# [('a', 'b', 'c'), (1, 2, 3)]
```

Let's do one more.

```
print(list(zip(['a', 1], ['b', 2], ['c', 3], ['d', 4])))
# [('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
```

So what if we have an iterable of tuples? Well ... we can unpack them.

```
l1, l2 = zip(*tuples)
```

Back to TILs.