unpacking first few items of iterable

Terry Reedy tjreedy at udel.edu
Thu Dec 13 16:36:58 EST 2012


On 12/13/2012 3:09 PM, MRAB wrote:
> On 2012-12-13 19:37, Daniel Fetchinson wrote:
>> Hi folks, I swear I used to know this but can't find it anywhere:
>>
>> What's the standard idiom for unpacking the first few items of an
>> iterable whose total length is unknown?

An hinted by some of the answers, this is not a complete specification.

>> Something like
>>
>> a, b, c, _ = myiterable
>>
>> where _ could eat up a variable number of items, in case I'm only
>> interested in the first 3 items?

The literal answer given by demian, a,b,c,*_=iterable, has some good 
uses but fails on an infinite iterable, and otherwise exhausts iterators 
and creates a potentially long sequence that, by the specification, is 
not needed. Mitya's alternative of slicing, seq[:3] requires a directly 
sliceable sequence rather than just an iterable.

> You could do this:
>
> from itertools import islice
> a, b, c = islice(myiterable, 3)

This works for any iterable and the only discarded temporary is a 
sequence of three items (needed so either all bindings work or none are 
made).

If you want to bind a default values if iterable has less than 3 values, 
one way is

 >>> a,b,c = itertools.islice(itertools.chain(itertools.islice((1,2), 
3), [None]*3), 3)
 >>> a,b,c
(1, 2, None)

Perhaps clearer is

 >>> a,b,c = [None]*3
 >>> it = iter((1,2))
 >>> try:
	a = next(it)
	b = next(it)
	c = next(it)
except StopIteration:
	pass

 >>> a,b,c
(1, 2, None)

This has the advantage that if iterable has more than 3 items, 'it' is 
available to iterate over the rest. This is the standard idiom for 
removing a couple of special items before iterating over the remainder 
(when one does not want the remainder as a concrete list).

-- 
Terry Jan Reedy




More information about the Python-list mailing list