让我们说我有这样的发电机:
def a(data):
for val in data:
yield val
让我们说我想将这个生成器包装在另一个生成器b
中,它只生成a
中的一些值,具体取决于它们的值。 b
应该能够将从调用方发回的值转发给a
。我知道在另一个生成器中包装生成器的最新方法是使用yield from
语句。类似的东西:
def b(data):
yield from val = a(data) if val == "foo"
我知道语法是错误的(只是为了克服这个想法),所以我想知道是否有正确的方法让yield from
使用条件语句。或者我应该使用其他一些构造吗?
答案 0 :(得分:1)
正如您所说,yield from
仅适用于您希望从包装的生成器传递所有内容的情况。如果您不想这样,则需要手动迭代包装的生成器并执行您想要的操作:
def b(data):
for value in a(data):
if some_condition(value):
yield value
# otherwise don't yield it.
如果你想处理send
,你也需要自己处理。这是一个简单的例子,您可以使用它来查看正在发生的事情:
def a():
sent = yield "Begin"
for x in [1, 2, 3]:
if sent:
sent = yield "You sent {0}".format(sent)
else:
sent = yield x
def b():
gen = a()
val = yield next(gen)
while True:
wrappedVal = gen.send(val)
if wrappedVal == 2:
continue
val = yield wrappedVal
在此示例中,基本上b
“隐藏”值{2},如果它由a
产生。 (我从我对this question的回答中对此进行了调整,这类似于包装生成器,但方式略有不同。但是,你可能会发现那里的讨论很有用。)
但是,这样做时你需要非常小心。由于b
可能会跳过a
中的值,因此尝试将send
值转换为b
的任何来电者都可能无法获得预期结果,因为b
可能会跳过意外的地方。在您使用send
的情况下,通常意味着调用者会监视生成器以获取某些信息,这些值会传递某些信息,然后将值作为响应发送回来。如果中间为b
,则此通信可能会不同步。例如,假设a
产生一条“消息”,b
向呼叫者发送消息,然后呼叫者发回一个响应,然后b
发送给a
。但假设b
吞下a
的回复。这将给调用者带来问题。您仍然可以使其工作,但这只是意味着您必须非常谨慎地编写b
来构建a
API所期望的任何通信渠道。
答案 1 :(得分:0)
由于看起来我无法将条件合并到<input type="button" onclick="printDiv('printableArea')" value="print a div!" />
,我通过处理手动关注的案例解决了这个问题。这就是我最终的结果:
yield from