Question: what's the difference between the two ways to unzip two zipped lists?

```
assert isinstance(X, list)
assert isinstance(X[0], tuple)
assert isinstance(X[0][0], list)
assert isinstance(X[0][0][0], dict)

X_model = []
X_synth = []
for row in X:
    X_model.append(row[0])
    X_synth.append(row[1])

```

X\_model is now a list of list of dict

```
X_model, X_synth, = zip(*X)

```

X\_model is a tuple of list of dicts
shouldn't the results be the same?

Answer: 
Let's use an example. For simplicity sake, instead of using a list of dicts let's use numbers. Notice the first element of every tuple is odd and the second element of every tuple is even.

```
>>> X = [(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]
>>> X_model = []
>>> X_synth = []
>>> for row in X:
...     X_model.append(row[0])
...     X_synth.append(row[1])
...
>>> X_model
[1, 3, 5, 7, 9]
>>> X_synth
[2, 4, 6, 8, 10]
>>> X_model, X_synth = zip(*X)
>>> X_model
(1, 3, 5, 7, 9)
>>> X_synth
(2, 4, 6, 8, 10)

```

Let's consider `zip(*X)`. `zip(*X)` is equivalent to

```
zip((1, 2), (3, 4), (5, 6), (7, 8), (9, 10))

```

From the [Python Docs](https://docs.python.org/2/library/functions.html#zip)

> 
> zip: 
>  This function returns a **list of tuples**, where the i-th tuple contains the i-th element from each of the argument sequences or iterables.
> 
> 
> 

Hence zip will return a **list of tuples** where the 0th tuple contains the 0th element from each argument (all odd numbers) and the 1st tuple contains all the 1st element from each argument (all even numbers)

```
X_model, X_synth = [(1, 3, 5, 7, 9), (2, 4, 6, 8, 10)]

```
The equivalent to `zip()` would be:

```
X_model = tuple(x for x, _ in X)
X_synth = tuple(x for _, x in X)

```

But this isn't very efficient as it cycles `X` twice.
Note: `tuple`s are immutable, so you can't efficiently do it in a loop as you would be creating a new tuple each time.