[Python-ideas] How assignment should work with generators?

Chris Angelico rosuav at gmail.com
Mon Nov 27 04:40:21 EST 2017


On Mon, Nov 27, 2017 at 8:17 PM, Kirill Balunov <kirillbalunov at gmail.com> wrote:
> In many cases it is possible to do this right now, but in too verbose way:
>
>>>> x, y = islice(gen(), 2)
>
> But it seems for me that:
>
>>>> x, y = gen()
>
> Looks the same, easy to follow and not so verbose.

This, AIUI, is the nub of the proposal. I don't like the proposed
solution, but if there's some alternative way to say "and then ignore
the rest", that would be much safer.

You said:

> 3. Optimized case for x,y,*z = iterator

It has to be semantically different from that, though. Consider these
two generators:

def gen1():
    for _ in range(5):
        print("Yielding!")
        yield "spam"
    yield "ham"

def gen2():
    yield 1
    yield 2
    yield 3
    while True:
        yield 4

If you use "x, y, *z = gen1()", you'll trigger all the prints and
completely consume the generator. With gen2(), you'll get an infinite
loop. Both of those are semantically different from the islice
behaviour, which would consume only that part that you're looking for.

What would be far safer is a special syntax that makes it clear that
you are not assigning those extra values anywhere. Something along
these lines has been proposed a number of times, and I think it's
probably about time a PEP was written up, if only to get rejected.
Here are a few syntaxes that I believe have been proposed at various
times:

x, y = islice(iter, 2) # status quo
x, y = iter # your proposal
x, y, = iter # omit last destination
x, y, * = iter # unpack into nothing
x, y, ... = iter # assigning to Ellipsis
x, y, *... = iter # as above but clearly sequencing

And there are a few others too. Every one of them has its downsides,
none is perfect. (Personally, I think one of the Ellipsis options is
likely the best, or perhaps the least-bad.) Want to spearhead the PEP?

ChrisA


More information about the Python-ideas mailing list