unpacking first few items of iterable

Peter Otten __peter__ at web.de
Thu Dec 13 17:22:20 EST 2012


Terry Reedy wrote:

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

If something doesn't look natural I usually shuffle around my code a bit. In 
this case I might end up with a helper function:

def work_with_abc(a=None, b=None, c=None, *discarded):
     ...
work_with_abc(*myiterable)

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

Or

it = iter(myiterable)
a = next(it, None)
b = next(it, None)
c = next(it, 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).






More information about the Python-list mailing list