Why does the โ€œexit fromโ€ (division of the generator) attachment lead to the completion of the value โ€œNoโ€?

Is it possible to nest yield from expressions?

The simple form is obvious:

 def try_yield1(): x = range(3) yield from x 

What produces:

 0 1 2 

But what if I have nested generators?

 def try_yield_nested(): x = [range(3) for _ in range(4)] yield from ((yield from y) for y in x) 

This gives:

 0 1 2 None # why? 0 1 2 None # ... 0 1 2 None # ... 

Why does it create None if I used yield from (even if it is nested)?

I know I can do something like:

 from itertools import chain def try_yield_nested_alternative(): x = [range(3) for _ in range(4)] yield from chain.from_iterable(x) 

Which gives the same conclusion as None (which I expect). I can also write a simple loop:

 for x in [range(3) for _ in range(3)]: yield from x 

But I thought it would be more pythonic to use nested delegation (preferably even yield from x from y or yield from x for x in y , but this is not the correct syntax). Why is this not working as I expect?

+5
source share
1 answer

yield is an expression, it will evaluate everything you send(value) . Simply put, if you don't send anything, you will get the output None , because the yield value will be None .

yield from itself is None , and you use two of them. On the second yield from you repeat the list that the generator introduces with the elements of this list, but you also use yield from to return this generator expression, which returns the list, and also itself, which is equivalent to None at each iteration, so after each iteration of the range of elements you get None .

Essentially this is what happens:

  • (yield from y) for y in x gives values, [0, 1, 2]
  • yield from gives the values โ€‹โ€‹from the previous, as well as yield from from the previous, which is None .
  • Rate to [0, 1, 2], and then add a None due to yield from in (yield from y) for y in x .

Unfortunately, there is no way to get rid of the None output due to the nature of the expression. You are better off using from_iterable .

A source explaining the expression yield; https://docs.python.org/2.5/ref/yieldexpr.html

+7
source

Source: https://habr.com/ru/post/1266674/


All Articles