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(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