[Python-Dev] Tricky way of of creating a generator via a comprehension expression

Ivan Levkivskyi levkivskyi at gmail.com
Sat Nov 25 09:55:28 EST 2017


On 25 November 2017 at 04:30, Guido van Rossum <guido at python.org> wrote:

> On Fri, Nov 24, 2017 at 4:22 PM, Guido van Rossum <guido at python.org>
> wrote:
>
>> The more I hear about this topic, the more I think that `await`, `yield`
>> and `yield from` should all be banned from occurring in all comprehensions
>> and generator expressions. That's not much different from disallowing
>> `return` or `break`.
>>
>
> From the responses it seems that I tried to simplify things too far. Let's
> say that `await` in comprehensions is fine, as long as that comprehension
> is contained in an `async def`. While we *could* save `yield [from]` in
> comprehensions, I still see it as mostly a source of confusion, and the
> fact that the presence of `yield [from]` *implicitly* makes the surrounding
> `def` a generator makes things worse. It just requires too many mental
> contortions to figure out what it does.
>

There were some arguments that `await` is like a function call, while
`yield` is like `return`.
TBH, I don't really like these arguments since to me they are to vague.
Continuing this logic one can say that
`return` is just a fancy function call (calling continuation with the
result). To me there is one clear distinction:
`return` and `break` are statements, while `yield`, `yield from`, and
`await` are expressions.

Continuing the topic of the ban, what exactly should be banned? For example
will this still be valid?

    def pack_two():
        return [(yield), (yield)]  # Just a list display

I don't see how this is controversial. It is clear that `pack_two` is a
generator.
If this is going to be prohibited, then one may be surprised by lack of
referential transparency, since this will be valid:

    def pack_two():
        first = (yield)
        second = (yield)
        return [first, second]

If the first example will be allowed, then one will be surprised why it
can't be rewritten as

    def pack_two():
        return [(yield) for _ in range(2)]

I have found several other examples where it is not clear whether they
should be prohibited with `yield` or not.

I still propose to rule out all of the above from generator expressions,
> because those can escape from the surrounding scope.
>

Here I agree. Also note that the above problem does not apply to generator
expressions since (x, x) and (x for _ in range(2)) are
two very different expressions.

--
Ivan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20171125/034060fc/attachment.html>


More information about the Python-Dev mailing list