# [Tutor] Strange zip syntax

Emeka emekamicro at gmail.com
Fri Sep 16 18:18:44 CEST 2011

```iBrett,

iter

On Fri, Sep 16, 2011 at 3:35 AM, Brett Ritter <swiftone at swiftone.org> wrote:

> myself temporarily stymied by one line it in:
>
> zip(*[iter(a)]*2)
>
> Used like this:
>
> >>> a = ['a','1','b','2','c','3']
> >>> zip(*[iter(a)]*2)
> [('a', '1'), ('b', '2'), ('c', '3')]
>
> While I'm unlikely to use such a construct (if I can't easily follow
> it now, I or my successor likely won't follow it should it need to be
> debugged sometime in the future), I found the education I got in
> deciphering it was worth the effort.  I'm sharing it here so others
> can benefit from my puzzlement.
>
> iter(a) returns a list iterator for a.  See help(iter) for more.
> [iter(a)] is a list containing one element, an iterator.  This is
> created only so we can do the below:
> [iter(a)]*2 is a list containing two elements, each the SAME list iterator.
> For simplicity, let's break this out for further analysis:
>
> >>> b = iter(a)
> >>> c = [b,b]
>

iter(c) returns listiterator

>
> *[iter(a)]*2 flattens the list when passed into a function call.
> Using our more verbose but simple syntax: *c.  This only works when
> passed to a function.
> zip() creates tuples each holding the Nth elements from a number of
> sequences.  See help(zip) for more.
> Thus, zip(a) or zip(a,a) would return:
> >>> zip(a)
> [('a',), ('1',), ('b',), ('2',), ('c',), ('3',)]
> >>> zip(a,a)
> [('a', 'a'), ('1', '1'), ('b', 'b'), ('2', '2'), ('c', 'c'), ('3', '3')]
>
> What happens when we pass an iterator to zip?  That's not mentioned in
> the docstring blurb.
> >>> zip(iter(a))
> [('a',), ('1',), ('b',), ('2',), ('c',), ('3',)]
> Answer: It works as intended.
>
> Now we come to the magic of this little snippet.
> zip(iter(a),iter(a)) wouldn't work, because each call to iter(a)
> returns a DIFFERENT iterator.
> >>> zip(iter(a), iter(a))
> [('a', 'a'), ('1', '1'), ('b', 'b'), ('2', '2'), ('c', 'c'), ('3', '3')]
>
> But by creating the list of two elements each of which is the SAME
> iterator, as each is asked to iterate it advances the common element
> indicator:
> >>> zip(*c)
> [('a', '1'), ('b', '2'), ('c', '3')]
> Notice that the flattening is required, because zip needs to get
> multiple arguments:
> >>> b = iter(a)  #our original iterator is spent, so we're assigning a new
> one
> >>> c = [b,b]
> >>> zip(c)   #Not flattened, is just a single list, like a.
> [(<listiterator object at 0x024E32D0>,), (<listiterator object at
> 0x024E32D0>,)]
> >>> zip(b,b)   # here it is two iterators sent to zip() (though they happen
> to be the SAME iterator)
> [('a', '1'), ('b', '2'), ('c', '3')]
>
> I hope some of you enjoy playing with this, and hopefully someone
> learned something useful!  While I'm not likely to use the listed
> form, I can very well see myself saying:
>
> >>> a = ['a','1','b','2','c','3']   #well, I can see myself using this with
> meaningful variable names
> >>> b = iter(a)
> >>> zip(b,b)  # Group in sets of 2 elements
>
> --
> Brett Ritter / SwiftOne
> swiftone at swiftone.org
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> To unsubscribe or change subscription options:
> http://mail.python.org/mailman/listinfo/tutor
>

--
*Satajanus  Nig. Ltd

*
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/tutor/attachments/20110916/af4c6b7d/attachment.html>
```