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

Kirill Balunov kirillbalunov at gmail.com
Mon Nov 27 05:45:20 EST 2017


2017-11-27 12:40 GMT+03:00 Chris Angelico <rosuav at gmail.com>:

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


Yes, it is. For me, x,y = gen() underlines the lazy nature of generators.


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

Of course, everyone has a subjective assessment of what is good and what is
bad. But here I am in something agree with you that at the present time some
alternative way would be much safer. But if started from scratch, it seems
to me natural to emphasize the nature of generators and iterators.


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


The idea is not to consume generator completely, but to get enough values
to bind to x and y. It should be equivalent to islice(iter, 2), and perceiveв
as "bind x, y, where you don't need values for z at all".

x, y = islice(iter, 2) # status quo
> x, y = iter # your proposal
>

As I wrote above, I would like to see them equivalent

x, y, = iter # omit last destination
>

I don't like this, it is hard to notice this nuance. It is valid to have
trailing comma (and I find it to be a brilliant feature to have (x,y)
equivalent to (x,y,)).
This reminds me of  `  in Python2, although I never used it and start my
journey with Python3.


> x, y, * = iter # unpack into nothing
>

Maybe, I like it.


> x, y, ... = iter # assigning to Ellipsis
> x, y, *... = iter # as above but clearly sequencing
>

Yes, it is nice to see Ellipsis as zero-length deques (or throw away
container), it can be used also in the middle of list of targets. What I
don't like about last three examples, that they imply by their form to be
some kind of iteration which must completely consume the generator, which
is opposite to the proposed idea. Moreover, this will not work with
infinite generators, falling into infinite loop.


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

To be honest, I'm quite new to the entire ecosystem of Python. Therefore,
someone can perceive this as an ordinary attempt by a novice to change
everything that is bad in his opinion. In addition, it seems to me that
these changes, if approved, can not be made earlier than Python3.8, so I
would like to get some feedback first. Nevertheless these words should not
be taken as a renouncement, I would be happy and very interested in writing
PEP and implementing it. But not to get stuck I need some support and
guidelines from interested dev.

With kind regards, -gdg
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20171127/e3352780/attachment-0001.html>


More information about the Python-ideas mailing list