iBrett, iter
On Fri, Sep 16, 2011 at 3:35 AM, Brett Ritter <swift...@swiftone.org> wrote: > I ran into this article ( > http://blog.adku.com/2011/09/hodgepodge-of-python.html ) and found > 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 > swift...@swiftone.org > _______________________________________________ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > http://mail.python.org/mailman/listinfo/tutor > -- *Satajanus Nig. Ltd *
_______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor