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

Ivan Levkivskyi levkivskyi at gmail.com
Wed Nov 22 12:36:20 EST 2017


On 22 November 2017 at 18:15, Paul Moore <p.f.moore at gmail.com> wrote:

> On 22 November 2017 at 16:47, Ivan Levkivskyi <levkivskyi at gmail.com>
> wrote:
> > On 22 November 2017 at 17:43, Paul Moore <p.f.moore at gmail.com> wrote:
> >>
> >> On 22 November 2017 at 16:30, Ivan Levkivskyi <levkivskyi at gmail.com>
> >> wrote:
> >> > On 22 November 2017 at 17:24, Antoine Pitrou <solipsis at pitrou.net>
> >> > wrote:
> >> >> Given a comprehension (e.g. list comprehension) is expected to work
> >> >> nominally as `constructor(generator expression)`
> >> >
> >> > As Yury just explained, these two are not equivalent if there is an
> >> > `await`
> >> > in the comprehension/generator expression.
> >>
> >> As Antoine said, people *expect* them to work the same.
> >
> >
> > The difference is that a generator expression can be used independently,
> one
> > can assign it to a variable etc. not necessary to wrap it into a list()
> > Anyway, can you propose an equivalent "defining" code for both?
> Otherwise it
> > is not clear what you are defending.
>
> [...snip...]
>
> 1. List comprehensions expand into nested for/if statements in the
> "obvious" way - with an empty list created to start and append used to
> add items to it.
>    1a. Variables introduced in the comprehension don't "leak" (see below).
> 2. Generator expressions expand into generators with the same "nested
> loop" behaviour, and a yield of the generated value.
> 3. List comprehensions are the same as list(the equivalent generator
> expression).
>

Great, I agree with all three rules.
But there is a problem, it is hard to make these three rules consistent in
some corner cases even _without async_.
For example, with the original problematic example, it is not clear to me
how to apply the rule 2 so that it is consistent with 3:

def fun_comp():
    return [(yield i) for i in range(3)]

def fun_gen():
    return list((yield i) for i in range(3))

I think the solution may be to formulate the rules in terms of the iterator
protocol (__iter__ and __next__).
I will try to think more about this.

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


More information about the Python-Dev mailing list