6

Given the zen of python why is zip(*) used to unzip instead of some function named unzip()? For example Transpose/Unzip Function (inverse of zip)? shows how to unzip a list.

>>> zip(*[('a', 1), ('b', 2), ('c', 3), ('d', 4)])
[('a', 'b', 'c', 'd'), (1, 2, 3, 4)]

How is that more:

  • Beautiful than ugly
  • Explicit than implicit
  • Simple than complex
  • Readable
  • etc.

then

>>> unzip([('a', 1), ('b', 2), ('c', 3), ('d', 4)])

?

What am I missing here?

Community
  • 1
  • 1
SpeedCoder5
  • 8,188
  • 6
  • 33
  • 34
  • If this is not an upvotable question, how can it be improved? – SpeedCoder5 Jan 07 '16 at 15:05
  • This is `*`: https://docs.python.org/2/tutorial/controlflow.html#unpacking-argument-lists – deceze Jan 07 '16 at 15:06
  • As for the rest, *"there should be __one__ obvious way to do it."* Since `zip(*)` *can* do it and `*` is a very commonly used operator, why *should* there be an `unzip` to do the same thing? – deceze Jan 07 '16 at 15:07
  • 8
    By doing `zip(*[...])`, you're not unzipping. You're still zipping. That's what you're missing. – Vincent Savard Jan 07 '16 at 15:12
  • I realize this is a noob question. I am looking to understand. Are the python zen principles listed in order of priority? Is your answer that using * to unpack the argument list makes unzip more widely versatile while at the same time providing only one way to do it? – SpeedCoder5 Jan 07 '16 at 15:16
  • What would `unzip` do? It would do exactly the same as `zip`, but accept its arguments as a list instead of as separate arguments. Sounds extremely redundant to me when that difference is already generalised in the `*` operator. – deceze Jan 07 '16 at 15:17
  • 2
    @ Vincent Savard - I'd mark that as the answer. Thanks. – SpeedCoder5 Jan 07 '16 at 15:18

1 Answers1

10

You're not actually unzipping when you do zip(*your_list). You're still zipping.

zip is a function that can take as many arguments as you want. In your case, you essentially have four different sequences that you want to zip: ('a', 1), ('b', 2), ('c', 3) and ('d', 4). Thus, you want to call zip like this:

>>> zip(('a', 1), ('b', 2), ('c', 3), ('d', 4))
[('a', 'b', 'c', 'd'), (1, 2, 3, 4)]

But your sequences aren't in separate variables, you just have a list which contains them all. This is where the * operator comes in. This operator unpacks the list in a way that each element of your list becomes an argument to the function.

This means that when you do this:

your_list = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
zip(*your_list)

Python calls zip which each element of your list as an argument, like this:

zip(('a', 1), ('b', 2), ('c', 3), ('d', 4))

This is why an unzip function isn't necessary: Unzipping is just another kind of zip, and is easily achievable with just the zip function and the * operator.

Vincent Savard
  • 34,979
  • 10
  • 68
  • 73