Why does `yield from` in a generator expression yield `None`s?

∥☆過路亽.° 提交于 2020-01-03 17:45:14

问题


I have the following code:

import itertools
for c in ((yield from bin(n)[2:]) for n in range(10)):
    print(c)

The output is:

 0
 None
 1
 None
 1
 0 
 None
 1
 1
 None

... etc. Why do the Nones appear? If I instead have:

def hmm():
 for n in range(10):
     yield from bin(n)[2:]

for c in hmm():
    print(c)

Then I get what I would expect:

0
1
1
0
1
1

... etc. Further, is there a way to write it as the generator expression to get the same result as the latter?


回答1:


yield is an expression, and its value is whatever is sent into the generator with send. If nothing is sent in, the value of yield is None. In your example yield from yields the values from the list, but the value of the yield from expression itself is None, which is yielded at each iteration of the enclosing generator expression (i.e., every value of range(10)).

Your example is equivalent to:

def hmm():
    for n in range(10):
        yield (yield from bin(n)[2:])

for item in hmm():
    print(item)

Note the extra yield.

You will always have this issue if you try to use yield in a generator expression, because the generator expression already yields its target values, so if you add an explicit yield, you are adding an extra expression (the yield expression) whose value will also be output in the generator. In other words, something like (x for x in range(5)) already yields the numbers in range(5); if you do something like ((yield x) for x in range(5)), you're going to get the values of the yield expression in addition to the numbers.

As far as I know, there is no way to get the simple yield from behavior (without extra Nones) using a generator comprehension. For your case, I think you can achieve what you want by using itertools.chain.from_iterable:

for c in itertools.chain.from_iterable(bin(n)[2:] for n in range(10)):
    print(c)

(Edit: I realized you can get the yield from behavior in a generator comprehension by using nested for clauses: x for n in range(10) for x in bin(n)[2:]. However, I don't think this is any more readable than using itertools.chain.)



来源:https://stackoverflow.com/questions/26979803/why-does-yield-from-in-a-generator-expression-yield-nones

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!