在Python中将多个值传递到生成器

时间:2017-05-16 15:33:34

标签: python arguments generator

我想知道是否可以在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()通话中完成,还是需要多次通话?

1 个答案:

答案 0 :(得分:1)

第一个答案:val是一个完全任意的名称,你可以在这里使用任何有效的python标识符。 counter&#34;知道&#34;关于它,因为它明确地将它绑定到(yield i)表达式的值,如果没有发送任何内容(普通None调用),则为next(it)或传递给it.send()的任何内容

第二:send()只取一个值,但没有什么能阻止你传递tuplelist(只要您的生成器正确处理它)。

编辑:在评论中回答您的其他问题

  

除了循环的最后一次迭代之外,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()?

上面的答案 - 你实际上可以自己找到;)