variable length tuple assignment

Steven D'Aprano steve at pearwood.info
Wed Feb 25 18:08:25 EST 2009


Tim Chase wrote:

> As an aside, as of the last time I read the PEP[1] on this, I
> believe it exhausts (or attempts to exhaust) any iterator.  IMHO,
> I think this exhausting is a bad idea because it prevents things like
> 
>    def numbers(start=0):
>      i = start
>      while True:
>        yield i
>        i += 1
> 
>    CONST_A, CONST_B, CONST_C, *rest = numbers()
> 
> which will hang in current Py3.0 until you blow a stack or
> overrun your heap somewhere because it will try to exhaust the
> infinite loop.  

But what else can it do? Do you expect Python to read your mind and
magically know when you intend to use rest and when you're intending to
just throw it away?

Perhaps Python could do that, via static analysis -- if rest is never used
again, don't bother exhausting the iterator. But that will lead to
differences in iterators that have side-effects. It will also have a subtle
difference in behaviour here:

it = xrange(5)  # for example
a, b, c, *rest = it
L = list(it)  # L is now [3, 4]

versus

a, b, c, *rest = xrange(5)
parrot(rest)
L = list(it)  # L is now []


> It also changes the type from iter() to list() 
> for the remaining content (not as grevious).

But that's what unpacking does. It would be a major semantic change for 

x, *s = some_iterator

to make s an alias of some_iterator. And why would you want it to? If you
do, just do this:

x, s = some_iterator.next(), some_iterator



-- 
Steven




More information about the Python-list mailing list