你可能正在尋找的是send
方法,它允許一個值爲發送到一個生成器。 The reference提供了一個例子:
>>> def echo(value=None):
... print "Execution starts when 'next()' is called for the first time."
... try:
... while True:
... try:
... value = (yield value)
... except Exception, e:
... value = e
... finally:
... print "Don't forget to clean up when 'close()' is called."
...
>>> generator = echo(1)
>>> print generator.next()
Execution starts when 'next()' is called for the first time.
1
>>> print generator.next()
None
>>> print generator.send(2)
2
>>> generator.throw(TypeError, "spam")
TypeError('spam',)
>>> generator.close()
Don't forget to clean up when 'close()' is called.
讓我舉我自己的例子。 (當心上面的代碼的Python 2.6,但低於我會寫的Python 3; py3k ref!):
>>> def amplify(iter, amp=1):
... for i in iter:
... reply = (yield i * amp)
... amp = reply if reply != None else amp
...
>>> it = amplify(range(10))
>>> next(it)
0
>>> next(it)
1
>>> it.send(3) # 2 * 3 = 6
6
>>> it.send(8) # 3 * 8 = 24
24
>>> next(it) # 4 * 8 = 32
32
當然,如果你真的願意,你也可以做到這一點沒有send
。例如。通過封裝生成一個類中(但它不是幾乎一樣優雅!):
>>> class MyIter:
... def __init__(self, iter, amp=1):
... self.iter = iter
... self.amp = amp
... def __iter__(self):
... for i in self.iter:
... yield i * self.amp
... def __call__(self):
... return iter(self)
...
>>> iterable = MyIter(range(10))
>>> iterator = iterable()
>>> next(iterator)
0
>>> next(iterator)
1
>>> iterable.amp = 3
>>> next(iterator)
6
>>> iterable.amp = 8
>>> next(iterator)
24
>>> next(iterator)
32
更新:好了,現在你已經更新了你的問題,讓我有這個問題的另一個刺。也許這就是你的意思?
>>> def amplify(iter, loc={}):
... for i in iter:
... yield i * loc.get('amp', 1)
...
>>> it = amplify(range(10), locals())
>>> next(it)
0
>>> next(it)
1
>>> amp = 3
>>> next(it)
6
>>> amp = 8
>>> next(it)
24
>>> next(it)
32
請注意locals()
應被視爲只讀,並且與作用域有關。正如你所看到的,你需要明確地將locals()
傳遞給生成器。我看不到這個...
非常感謝你的例子。它接縫,我忘了在我的問題的第一個編輯中添加關於「發送」的評論。 – Juergen 2009-07-17 08:41:54
好的,我現在增加了`locals()`的另一個版本。也許這適合你的需求? – Stephan202 2009-07-17 14:26:23