为什么在生成器表达式中`yield from`会产生`None`s?

时间:2014-11-17 18:54:34

标签: python python-3.x generator yield generator-expression

我有以下代码:

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

...等。此外,有没有办法把它写成生成器表达式以获得与后者相同的结果?

1 个答案:

答案 0 :(得分:10)

yield是一个表达式,其值是使用send发送到生成器的任何值。如果未发送任何内容,则yield的值为None。在您的示例中,yield from生成列表中的值,但yield from表达式本身的值为None,它在封闭生成器表达式的每次迭代时生成(即,{{1的每个值) }})。

您的示例相当于:

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行为(没有额外的Nones)。对于您的情况,我认为您可以使用yield from

达到您想要的效果
itertools.chain.from_iterable

(编辑:我意识到你可以通过使用嵌套的for c in itertools.chain.from_iterable(bin(n)[2:] for n in range(10)): print(c) 子句yield from获得生成器理解中的for行为。但是,我认为这不再具有可读性而不是使用x for n in range(10) for x in bin(n)[2:]。)