我很惊讶地发现,
ge=(x*x for x in [1,2,3])
接受.send
方法。像任何其他生成器一样,第一次调用的参数必须为None
,但是其他调用的行为,例如ans=ge.send(99)
似乎与ans=next(ge)
相同。
我的99在哪里? ge中没有yield表达式,没有要分配的内容。注入的值只是被丢弃了(我怀疑),还是有些神秘?
有人看到吗?
答案 0 :(得分:3)
与您send
使用生成器函数创建的等效生成器相同:
def genfunc(outer_iterable):
for x in outer_iterable:
yield x*x
ge = genfunc([1, 2, 3])
也就是说send
参数被丢弃。
我们可以反汇编字节码以进一步确认:
import dis
ge=(x*x for x in [1,2,3])
print('Genexp:')
dis.dis(ge)
def genfunc(outer_iterable):
for x in outer_iterable:
yield x*x
ge = genfunc([1, 2, 3])
print()
print('Generator function:')
dis.dis(ge)
Genexp:
3 0 LOAD_FAST 0 (.0)
>> 3 FOR_ITER 15 (to 21)
6 STORE_FAST 1 (x)
9 LOAD_FAST 1 (x)
12 LOAD_FAST 1 (x)
15 BINARY_MULTIPLY
16 YIELD_VALUE
17 POP_TOP
18 JUMP_ABSOLUTE 3
>> 21 LOAD_CONST 0 (None)
24 RETURN_VALUE
Generator function:
9 0 SETUP_LOOP 23 (to 26)
3 LOAD_FAST 0 (outer_iterable)
6 GET_ITER
>> 7 FOR_ITER 15 (to 25)
10 STORE_FAST 1 (x)
10 13 LOAD_FAST 1 (x)
16 LOAD_FAST 1 (x)
19 BINARY_MULTIPLY
20 YIELD_VALUE
21 POP_TOP
22 JUMP_ABSOLUTE 7
>> 25 POP_BLOCK
>> 26 LOAD_CONST 0 (None)
29 RETURN_VALUE
genexp和通过generator函数创建的generator具有非常相似的反汇编,在两者中,YIELD_VALUE
之后紧跟着POP_TOP
,该send
丢弃了从 private void iAbout_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
DevExpress.Utils.About.frmAbout dlg = new DevExpress.Utils.About.frmAbout("~");
dlg.ShowDialog();
}
发送来的任何值
答案 1 :(得分:0)
谢谢大家。所以是的,send的arg被丢弃了,但是 accepted 的事实似乎是一个异常。
这里已经评论了另一个相关的错误(第32139885页),在genexps中应禁止yield表达式,但事实并非如此。格式为ge=((yield x*x) for x in [1,2,3])
,并且.send()
有效。
然后,send
返回的答案是内部可迭代元素和send
的args的混合...如果我没记错的话,GvR在Python 3.8中写道: yield表达式)将被视为错误,并且在3.7中应表明已弃用。 (人们同意这令人困惑。)
但是我在Python 3.7(Anaconda,Windows 64)中进行了测试,但没有收到过时警告。无论如何,这似乎是一个实际的错误,而不是不推荐使用的功能。我相信目前没有什么可说的了...
JK