我想知道是否可以在Python中将几个值传递给生成器。我找到了一个传递过的例子:
def counter(maximum):
i = 0
while i < maximum:
val = (yield i)
# If value provided, change counter
if val is not None:
i = val
else:
i += 1
执行上述功能:
>>> it = counter(10)
>>> next(it)
0
>>> next(it)
1
>>> it.send(8)
8
>>> next(it)
9
>>> next(it)
Traceback (most recent call last):
File "t.py", line 15, in <module>
it.next()
StopIteration
问题是双重的。
首先是counter
函数如何知道变量val
?它似乎没有定义或传递到任何地方。是否存在强制我们使用此名称的约定,以防我们想将值传递给生成器?
第二个问题是我们如何将多个值传递给生成器?这可以在一次send()
通话中完成,还是需要多次通话?
答案 0 :(得分:1)
第一个答案:val
是一个完全任意的名称,你可以在这里使用任何有效的python标识符。 counter
&#34;知道&#34;关于它,因为它明确地将它绑定到(yield i)
表达式的值,如果没有发送任何内容(普通None
调用),则为next(it)
或传递给it.send()
的任何内容
第二:send()
只取一个值,但没有什么能阻止你传递tuple
或list
(只要您的生成器正确处理它)。
编辑:在评论中回答您的其他问题
除了循环的最后一次迭代之外,val总是不会是None吗?
为什么??? yield <whatever>
的执行是通过对生成器的正常迭代和对generator.send(something)
的显式调用来触发的。在第一种情况下,yield whatever
&#34;表达式的值#34; (技术上yield
是一个陈述,但因为它可以产生&#34;一个值,它的行为就像这里的表达式一样)是None
。在第二种情况下,它传递给.send()
的任何内容。
这与迭代次数或内部循环无关(可能不存在 - 你不必在生成器中有内循环)。
那就是,发电机&#34;冻结&#34;恰好遇到收益率
它暂停在yield
语句上的执行,并在下一次迭代或.send()
调用时继续:
>>> def gen(x):
... for i in xrange(x):
... print "before yield"
... wot = (yield x)
... print "after yield - wot is '%s'" % wot
... if wot is not None:
... x = wot
... print "x is now %s" % x
...
>>> g = gen(5)
>>> next(g)
before yield
5
>>> next(g)
after yield - wot is 'None'
before yield
5
>>> g.send(10)
after yield - wot is '10'
x is now 10
before yield
10
>>> next(g)
after yield - wot is 'None'
before yield
10
还是它实际上是通过条件,决定我应该是什么,产生它然后暂停执行,直到调用另一个next()?
上面的答案 - 你实际上可以自己找到;)