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

Cla*_*diu 4 python yield generator generator-expression python-3.x

我有以下代码:

import itertools
for c in ((yield from bin(n)[2:]) for n in range(10)):
    print(c)
Run Code Online (Sandbox Code Playgroud)

输出是:

 0
 None
 1
 None
 1
 0 
 None
 1
 1
 None
Run Code Online (Sandbox Code Playgroud)

......等等为什么会None出现?如果我改为:

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

for c in hmm():
    print(c)
Run Code Online (Sandbox Code Playgroud)

然后我得到了我期望的东西:

0
1
1
0
1
1
Run Code Online (Sandbox Code Playgroud)

...等等.还有一种方法可以将它写为生成器表达式以获得与后者相同的结果吗?

Bre*_*arn 11

yield是一个表达式,它的值是发送到生成器的任何值send.如果没有发送任何内容,则值为yieldNone.在您的示例中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)
Run Code Online (Sandbox Code Playgroud)

请注意额外的yield.

如果尝试yield在生成器表达式中使用,则始终会遇到此问题,因为生成器表达式已经生成其目标值,因此如果添加显式yield,则添加一个额外的表达式(yield表达式),其值也将在发电机.换句话说,像(x for x in range(5))已经产生数字的东西range(5); 如果你做了类似的事情((yield x) for x in range(5)),yield除了数字之外,你还要得到表达式的值.

据我所知,没有办法yield from使用生成器理解来获得简单的行为(没有额外的Nones).对于您的情况,我认为您可以通过以下方式实现您的目标itertools.chain.from_iterable:

for c in itertools.chain.from_iterable(bin(n)[2:] for n in range(10)):
    print(c)
Run Code Online (Sandbox Code Playgroud)

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