为什么生成器表达式中的"yield from"产生"None"? [英] Why does `yield from` in a generator expression yield `None`s?
问题描述
我有以下代码:
import itertools
for c in ((yield from bin(n)[2:]) for n in range(10)):
print(c)
输出为:
0
None
1
None
1
0
None
1
1
None
...等.为什么出现None
?如果我有:
def hmm():
for n in range(10):
yield from bin(n)[2:]
for c in hmm():
print(c)
然后我得到了我期望的结果:
0
1
1
0
1
1
...等.此外,有没有一种方法可以将其写为生成器表达式,以获得与后者相同的结果?
yield
是一个表达式,其值就是使用send
发送到生成器中的值.如果未发送任何内容,则yield
的值为无".在您的示例中,yield from
会从列表中产生值,但是yield from
表达式本身的值是None,这是在封闭的生成器表达式的每次迭代中产生的(即,每个range(10)
的值). >
您的示例等效于:
def hmm():
for n in range(10):
yield (yield from bin(n)[2:])
for item in hmm():
print(item)
请注意多余的yield
.
如果尝试在生成器表达式中使用yield
,则始终会遇到此问题,因为生成器表达式已经产生了其目标值,因此,如果添加显式的yield
,则会添加一个额外的表达式( yield
表达式),其值也将在生成器中输出.换句话说,像(x for x in range(5))
这样的东西已经产生了range(5)
中的数字.如果您执行类似((yield x) for x in range(5))
的操作,那么除了数字之外,您还将获得yield
表达式的值.
据我所知,没有办法使用生成器理解来获得简单的yield from
行为(没有额外的None).对于您的情况,我认为您可以通过使用itertools.chain.from_iterable
来实现您想要的目标:
for c in itertools.chain.from_iterable(bin(n)[2:] for n in range(10)):
print(c)
(我意识到您可以通过使用嵌套的for
子句:x for n in range(10) for x in bin(n)[2:]
在生成器理解中获得yield from
行为.但是,我认为这比使用itertools.chain
更具可读性. )
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 None
s 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?
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
.)
这篇关于为什么生成器表达式中的"yield from"产生"None"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!