Re: [Tutor] Python Idioms?

2015-04-01 Thread Steven D'Aprano
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?

2015-04-01 Thread Mark Lawrence

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?

2015-04-01 Thread Roel Schroeven

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?

2015-04-01 Thread Mark Lawrence

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?

2015-04-01 Thread Steven D'Aprano
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?

2015-04-01 Thread Steven D'Aprano
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?

2015-04-01 Thread Dave Angel

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?

2015-04-01 Thread Mark Lawrence

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?

2015-04-01 Thread Alan Gauld

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?

2015-04-01 Thread Wolfgang Maier

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?

2015-04-01 Thread Alan Gauld

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?

2015-04-01 Thread Jim Mooney
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