Do this as a list comprehension?

Mensanator mensanator at aol.com
Sat Jun 7 01:06:25 EDT 2008


On Jun 6, 10:33 pm, "Terry Reedy" <tjre... at udel.edu> wrote:
> "Mensanator" <mensana... at aol.com> wrote in message
>
> news:c55356a4-04a0-442e-ad84-f35156cdec9c at z72g2000hsb.googlegroups.com...
> On Jun 6, 1:44 am, "Terry Reedy" <tjre... at udel.edu> wrote:
>
>
>
>
>
> > "Mensanator" <mensana... at aol.com> wrote in message
>
> >news:bbd90051-36be-4378-9a27-2a47a5471d12 at a1g2000hsb.googlegroups.com...
> > | On Jun 5, 10:42?pm, John Salerno <johnj... at gmailNOSPAM.com> wrote:
> > | > Is it possible to write a list comprehension for this so as to
> > produce
> > a
> > | > list of two-item tuples?
> > | >
> > | > base_scores = range(8, 19)
> > | > score_costs = [0, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3]
> > | > print zip(base_scores, score_costs)
> > | >
> > | > I can't think of how the structure of the list comprehension would
> > work
> > | > in this case, because it seems to require iteration over two separate
> > | > sequences to produce each item in the tuple.
>
> > Which is exactly the purpose of zip, or its specialization enumerate!
>
> Aren't you overlooking the fact that zip() truncates the output
> to the shorter length iterable?
> =========================
> <message does not quote correctly>
> <me> No.
> =========================
> And since the OP foolishly
> hardcoded his range bounds, zip(base_scores,score_cost) will
> silently return the wrong answer if the base_count list grows.
> ============
> <me> So, to future proof his code he should better use
> zip(itertools.count(8), score_costs).  I consider this better than using
> enumerate to make the wrong pairing (with itertools.count(0)) and then
> correcting the mistake.

Mistake? How is starting at 0 a mistake? Because .count() can
start at 8, eliminating the i+8 construction? But what if
I wanted to count by two or want a sequence cubes that start
at 8? Can itertools do that? I would say knowing how to
manipulate a 0-based iterable will pay off more in the long
run. If you don't know how to get the index numbers you want
from enumerate(), itertools isn't going to help.

> ====================
> Surely enumerate() wasn't added to Python with no intention of
> ever being used.
> ========================
> <me> Of course not, so why suggest that is was?
> However, it was intended for the most common case when one wants to pair
> items with counts beginning with 0.
> =================================
>
> > Of course, enumerate(iterable) is just a facade over
> > zip(itertools.count(),
> > iterable)
>
> But if all I'm using itertools for is the count() function, why would
> I go to the trouble of importing it when I can simply use enumerate()?
> ====================================
> <me>I have no idea.  The purpose of enumerate is to be easy.
> But it is not so easy when it gives the wrong pairings.

The same can be said of zip() if you're not careful
about the size of the iterables. There is no substitute
for understanding how things work.

> ===================================
> Is it a couple orders of magnitude faster?
> =================================
> <me> Perhaps you do not understand 'facade' - the front part or face of
> something that you see.  

Well, I also understand the secondary meaning:
2. An artificial or deceptive front

> I was saying that enumerate is a face on a room
> containing zip and itertools.count, or the equivalent code thereof.

I thought you were trying to imply that to use enumerate()
is to be un-Pythonic, that _real_ programmers always use
itertools.

> Therefore, enumerate is an easy way to do a particular zip, not an
> alternative to zip.  

Ok, I mistook your use of 'facade' for arrogance,
just as the OP mistook my use of 'foolishly' for
arrogance. Ain't English wonderful?

> And there should be no significant performance
> difference, certainly for long sequences which make the additional lookups
> irrelevant.
>
> tjr



More information about the Python-list mailing list