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

Ivan Levkivskyi levkivskyi at gmail.com
Wed Nov 22 09:09:40 EST 2017


On 22 November 2017 at 14:53, Serhiy Storchaka <storchaka at gmail.com> wrote:

> 22.11.17 15:25, Ivan Levkivskyi пише:
>
>> I think this is indeed a problem.. For me the biggest surprise was that
>> `yield` inside a comprehension does not turn a surrounding function into
>> comprehension, see also
>> https://stackoverflow.com/questions/29334054/why-am-i-gettin
>> g-different-results-when-using-a-list-comprehension-with-coroutin
>>
>> In fact there is a b.p.o. issue for this https://bugs.python.org/issue1
>> 0544, it is assigned to me since July, but I was focused on other things
>> recently.
>> My plan was to restore the Python 2 semantics while still avoiding the
>> leak of comprehension variable to the enclosing scope (the initial reason
>> of introducing auxiliary "_make_list" function IIUC).
>> So that:
>>
>> 1) g = [(yield i) for i in range(3)] outside a function will be a
>> SyntaxError (yield outside a function)
>> 2) g = [(yield i) for i in range(3)] inside a function will turn that
>> enclosing function into generator.
>> 3) accessing i after g = [(yield i) for i in range(3)] will give a
>> NameError: name 'i' is not defined
>>
>> If you have time to work on this, then I will be glad if you take care of
>> this issue, you can re-assign it.
>>
>
> I have the same plan. I know how implement this for comprehensions, but
> the tricky question is what to do with generator expressions? Ideally
>
>     result = [expr for i in iterable]
>
> and
>
>     result = list(expr for i in iterable)
>
> should have the same semantic. I.e. if expr is "(yield i)", this should
> turn the enclosing function into a generator function, and fill the list
> with values passed to the generator's .send(). I have no idea how implement
> this.
>
>
Yes, generator expressions are also currently problematic with `await`:

>>> async def g(i):
...     print(i)
...
>>> async def f():
...     result = list(await g(i) for i in range(3))
...     print(result)
...
>>> f().send(None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f
TypeError: 'async_generator' object is not iterable

Maybe Yury can say something about this?

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


More information about the Python-Dev mailing list