Re: [Tutor] Python Idioms?
On Wed, Apr 01, 2015 at 09:59:30PM +0100, Mark Lawrence wrote: [snip mass quoting] > Yo are of course completely correct, I was conflating two different > threads :) Hey guys, how about trimming some of the excessive quoting in your posts? Especially if you're going to complain about the annoyance of top-posting, bottom-posting without trimming is actually *worse* and more distruptive to ease of reading. After I've flipped through two pages of quotes without any new comments at all, I'm sorely tempted to just hit Delete on the rest unread. -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Python Idioms?
On 01/04/2015 18:20, Roel Schroeven wrote: Mark Lawrence schreef: On 01/04/2015 11:50, Alan Gauld wrote: On 01/04/15 11:04, Wolfgang Maier wrote: On 04/01/2015 11:04 AM, Alan Gauld wrote: On 01/04/15 05:50, Jim Mooney wrote: s = [1,2,3,4,5,6,7,8] list(zip(*[iter(s)]*2)) [(1, 2), (3, 4), (5, 6), (7, 8)] Personally I'd have used slicing in this example: zip(s[::2],s[1::2]) With an emphasis on *in this example*. The idiom you are citing works on any iterable, not all of which support slicing and the slicing version requires two passes over the data. Agreed, but readability always trumps performance, unless performance is critical. In which case readability usually trumps performance. And especially on a beginners list. In which case I'll stick with the more-itertools pairwise() function Which does not the same thing. Original: s = [1,2,3,4,5,6,7,8] list(zip(*[iter(s)]*2)) [(1, 2), (3, 4), (5, 6), (7, 8)] Pairwise: >>> take(4, pairwise(count())) [(0, 1), (1, 2), (2, 3), (3, 4)] Greetings, Roel Yo are of course completely correct, I was conflating two different threads :) -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Python Idioms?
Mark Lawrence schreef: On 01/04/2015 11:50, Alan Gauld wrote: On 01/04/15 11:04, Wolfgang Maier wrote: On 04/01/2015 11:04 AM, Alan Gauld wrote: On 01/04/15 05:50, Jim Mooney wrote: s = [1,2,3,4,5,6,7,8] list(zip(*[iter(s)]*2)) [(1, 2), (3, 4), (5, 6), (7, 8)] Personally I'd have used slicing in this example: zip(s[::2],s[1::2]) With an emphasis on *in this example*. The idiom you are citing works on any iterable, not all of which support slicing and the slicing version requires two passes over the data. Agreed, but readability always trumps performance, unless performance is critical. In which case readability usually trumps performance. And especially on a beginners list. In which case I'll stick with the more-itertools pairwise() function Which does not the same thing. Original: s = [1,2,3,4,5,6,7,8] list(zip(*[iter(s)]*2)) [(1, 2), (3, 4), (5, 6), (7, 8)] Pairwise: >>> take(4, pairwise(count())) [(0, 1), (1, 2), (2, 3), (3, 4)] Greetings, Roel -- The saddest aspect of life right now is that science gathers knowledge faster than society gathers wisdom. -- Isaac Asimov Roel Schroeven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Python Idioms?
On 01/04/2015 14:16, Steven D'Aprano wrote: On Wed, Apr 01, 2015 at 12:06:33PM +0100, Mark Lawrence wrote: In which case I'll stick with the more-itertools pairwise() function which I pointed out on another thread just yesterday. From http://pythonhosted.org//more-itertools/api.html Returns an iterator of paired items, overlapping, from the original take(4, pairwise(count())) [(0, 1), (1, 2), (2, 3), (3, 4)] I betcha the implementation of pairwise is something really close to: def pairwise(iterable): it = iter(iterable) return itertools.izip(it, it) for Python 2, and for Python 3: def pairwise(iterable): it = iter(iterable) return zip(it, it) Not a bad attempt :) It's actually. def pairwise(iterable): """Returns an iterator of paired items, overlapping, from the original >>> take(4, pairwise(count())) [(0, 1), (1, 2), (2, 3), (3, 4)] """ a, b = tee(iterable) next(b, None) return zip(a, b) -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Python Idioms?
On Wed, Apr 01, 2015 at 12:06:33PM +0100, Mark Lawrence wrote: > In which case I'll stick with the more-itertools pairwise() function > which I pointed out on another thread just yesterday. From > http://pythonhosted.org//more-itertools/api.html > > > Returns an iterator of paired items, overlapping, from the original > > >>> take(4, pairwise(count())) > [(0, 1), (1, 2), (2, 3), (3, 4)] I betcha the implementation of pairwise is something really close to: def pairwise(iterable): it = iter(iterable) return itertools.izip(it, it) for Python 2, and for Python 3: def pairwise(iterable): it = iter(iterable) return zip(it, it) which is all well and good, but what if you want triplets, not pairs? def threewise(iterable): it = iter(iterable) return zip(it, it, it) I don't think it's very practical to include a *wise for every possible number of items... Let's deal some cards! import random cards = [] for value in "A 2 3 4 5 6 7 8 9 10 J Q K".split(): for suit in u"♠♣♦♥": cards.append(value + suit) random.shuffle(cards) deck = iter(cards) hands = zip(*[deck]*8) for name in "Groucho Chico Harpo Zeppo Gummo".split(): print("%s gets dealt %s" % (name, ','.join(next(hands I get these results, but being random of course you will get something different: Groucho gets dealt 8♣,2♠,5♥,7♣,8♦,7♠,6♥,8♥ Chico gets dealt Q♦,K♦,3♥,7♦,K♠,J♠,9♥,10♥ Harpo gets dealt 10♣,4♦,4♥,A♠,A♦,K♥,3♠,J♥ Zeppo gets dealt 5♣,A♥,3♦,Q♣,9♣,9♠,4♣,2♥ Gummo gets dealt J♦,Q♠,4♠,10♦,J♣,6♦,5♦,A♣ -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Python Idioms?
On Tue, Mar 31, 2015 at 09:50:43PM -0700, Jim Mooney wrote: > I'm looking at this and can't see how it works, although I understand > zipping and unpacking. The docs say it's a Python idiom. Does "idiom" mean > it works in a special way so I can't figure it out from basic principles? > It looks to me like the iterator in the list gets doubled, so the zip > should make it [(1,1),(2,2),(3,3),... ], not [(1,2),(3,4),...] > > What am I missing here? The secret is that list multiplication doesn't make *copies*, it replicates multiple references to the same object. > >>> s = [1,2,3,4,5,6,7,8] > >>> list(zip(*[iter(s)]*2)) > >>> [(1, 2), (3, 4), (5, 6), (7, 8)] Let's pull this apart and see how it ticks. It may actually be more obvious what is going on if we use more than two references, and do by hand what * does for us above. py> s = [100, 200, 300, 400, 500, 600, 700, 800, 900] py> it = iter(s) # One iterator object. py> next(it), next(it), next(it) # Call next three times. (100, 200, 300) py> args = [it, it, it] # Like [it]*3 py> for x in args: ... print(next(x)) # Like next(it). ... 400 500 600 We created *one* iterator. First we called next(it) three times, by hand, which yields the first three items in the list s. Then we stick the iterator in a new list three times, and loop over that, calling next() each time. That is equivalent to next(it) three more times, which gives us the next three items. Finally, we pass them to zip(), as separate arguments: py> list(zip(*args)) [(700, 800, 900)] Which gives us the next three items. At that point, we run out of items, and zip completes. Putting it (almost) all together now. Remember that `it` above, the iterator, is now exhausted. It has walked all the way through list s, so we need a new iterator to make it work again: py> list(it) # it is exhausted. [] py> it = iter(s) # So re-create it. py> list(zip(*[it]*3)) [(100, 200, 300), (400, 500, 600), (700, 800, 900)] We can avoid the temporary variable: py> list(zip(*[iter(s)]*3)) [(100, 200, 300), (400, 500, 600), (700, 800, 900)] -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Python Idioms?
On 04/01/2015 12:50 AM, Jim Mooney wrote: I'm looking at this and can't see how it works, although I understand zipping and unpacking. The docs say it's a Python idiom. Does "idiom" mean it works in a special way so I can't figure it out from basic principles? It looks to me like the iterator in the list gets doubled, so the zip should make it [(1,1),(2,2),(3,3),... ], not [(1,2),(3,4),...] What am I missing here? s = [1,2,3,4,5,6,7,8] list(zip(*[iter(s)]*2)) [(1, 2), (3, 4), (5, 6), (7, 8)] https://docs.python.org/3/library/functions.html#zip In that same thread, Peter Otten posted the following, which I think is probably a bit clearer: >>> flat_pairs = ['broadcast', '"d8on"', 'broadcast', '"d11on"'] >>> it = iter(flat_pairs) >>> pairs = list(zip(it, it)) >>> pairs That does exactly the same thing, but in the first one you can replace the '2' with a variable, to make variable sized tuples. In both cases, the trick is that the same iterator is used twice in the expression, so even though zip is taking one from each, there are no duplications. If you know the original data is a list, or at least that it can do slices, then you can do Alan's suggestion: zip(s[::2],s[1::2]) Or you could try: from itertools import islice pairs = zip(islice(s, 0, , 2), islice(s, 1, , 2)) -- DaveA ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Python Idioms?
On 01/04/2015 11:50, Alan Gauld wrote: On 01/04/15 11:04, Wolfgang Maier wrote: On 04/01/2015 11:04 AM, Alan Gauld wrote: On 01/04/15 05:50, Jim Mooney wrote: s = [1,2,3,4,5,6,7,8] list(zip(*[iter(s)]*2)) [(1, 2), (3, 4), (5, 6), (7, 8)] Personally I'd have used slicing in this example: zip(s[::2],s[1::2]) With an emphasis on *in this example*. The idiom you are citing works on any iterable, not all of which support slicing and the slicing version requires two passes over the data. Agreed, but readability always trumps performance, unless performance is critical. In which case readability usually trumps performance. And especially on a beginners list. In which case I'll stick with the more-itertools pairwise() function which I pointed out on another thread just yesterday. From http://pythonhosted.org//more-itertools/api.html Returns an iterator of paired items, overlapping, from the original >>> take(4, pairwise(count())) [(0, 1), (1, 2), (2, 3), (3, 4)] -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Python Idioms?
On 01/04/15 11:04, Wolfgang Maier wrote: On 04/01/2015 11:04 AM, Alan Gauld wrote: On 01/04/15 05:50, Jim Mooney wrote: s = [1,2,3,4,5,6,7,8] list(zip(*[iter(s)]*2)) [(1, 2), (3, 4), (5, 6), (7, 8)] Personally I'd have used slicing in this example: zip(s[::2],s[1::2]) With an emphasis on *in this example*. The idiom you are citing works on any iterable, not all of which support slicing and the slicing version requires two passes over the data. Agreed, but readability always trumps performance, unless performance is critical. In which case readability usually trumps performance. And especially on a beginners list. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Python Idioms?
On 04/01/2015 11:04 AM, Alan Gauld wrote: On 01/04/15 05:50, Jim Mooney wrote: s = [1,2,3,4,5,6,7,8] list(zip(*[iter(s)]*2)) [(1, 2), (3, 4), (5, 6), (7, 8)] Personally I'd have used slicing in this example: zip(s[::2],s[1::2]) With an emphasis on *in this example*. The idiom you are citing works on any iterable, not all of which support slicing and the slicing version requires two passes over the data. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Python Idioms?
On 01/04/15 05:50, Jim Mooney wrote: I'm looking at this and can't see how it works, although I understand zipping and unpacking. The docs say it's a Python idiom. Does "idiom" mean it works in a special way so I can't figure it out from basic principles? No idiom means a common pattern of usage in the community. In this case thats true of zip(), its less true of this case which is somewhat obscure. It looks to me like the iterator in the list gets doubled, so the zip should make it [(1,1),(2,2),(3,3),... ], not [(1,2),(3,4),...] What am I missing here? The fact that thew list contains a reference to an iterator so when you multiply by two you get two references to *the same* iterator. So each time the iterator gets accessed it returns the next number in the sequence, not the same number twice. s = [1,2,3,4,5,6,7,8] list(zip(*[iter(s)]*2)) [(1, 2), (3, 4), (5, 6), (7, 8)] Personally I'd have used slicing in this example: zip(s[::2],s[1::2]) Is that any clearer? -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Python Idioms?
I'm looking at this and can't see how it works, although I understand zipping and unpacking. The docs say it's a Python idiom. Does "idiom" mean it works in a special way so I can't figure it out from basic principles? It looks to me like the iterator in the list gets doubled, so the zip should make it [(1,1),(2,2),(3,3),... ], not [(1,2),(3,4),...] What am I missing here? >>> s = [1,2,3,4,5,6,7,8] >>> list(zip(*[iter(s)]*2)) >>> [(1, 2), (3, 4), (5, 6), (7, 8)] https://docs.python.org/3/library/functions.html#zip -- Jim ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor