一些用例使用generator和send()
带有send()生成器允许:
记住执行的内部状态
我们在做什么?
我们的数据目前状况如何?
返回值序列
接收input序列
这里有一些用例:
看着试图遵循食谱
让我们有一个配方,它需要按照某种顺序预定义一组input。
我们可能:
从配方创build一个watched_attempt实例
让它得到一些input
每个input都会返回有关当前在jar中的信息
与每个input检查,input是预期的(如果不是,则会失败)
def recipe(): pot = [] action = yield pot assert action == ("add", "water") pot.append(action[1]) action = yield pot assert action == ("add", "salt") pot.append(action[1]) action = yield pot assert action == ("boil", "water") action = yield pot assert action == ("add", "pasta") pot.append(action[1]) action = yield pot assert action == ("decant", "water") pot.remove("water") action = yield pot assert action == ("serve") pot = [] yield pot
要使用它,首先创buildwatched_attempt实例:
>>> watched_attempt = recipe() >>> watched_attempt.next() []
对.next()的调用是开始执行生成器所必需的。
返回值显示,我们的锅目前是空的。
现在按照配方预期做几个动作:
>>> watched_attempt.send(("add", "water")) ['water'] >>> watched_attempt.send(("add", "salt")) ['water', 'salt'] >>> watched_attempt.send(("boil", "water")) ['water', 'salt'] >>> watched_attempt.send(("add", "pasta")) ['water', 'salt', 'pasta'] >>> watched_attempt.send(("decant", "water")) ['salt', 'pasta'] >>> watched_attempt.send(("serve")) []
正如我们所看到的,这个锅最终是空的。
如果一个人不遵循这个秘诀,它就会失败(所看到的尝试做什么的结果会是什么样的 – 只是学习我们在给出指示时没有给予足够的重视。
>>> watched_attempt = running.recipe() >>> watched_attempt.next() [] >>> watched_attempt.send(("add", "water")) ['water'] >>> watched_attempt.send(("add", "pasta")) --------------------------------------------------------------------------- AssertionError Traceback (most recent call last) in () ----> 1 watched_attempt.send(("add", "pasta")) /home/javl/sandbox/stack/send/running.py in recipe() 29 30 action = yield pot ---> 31 assert action == ("add", "salt") 32 pot.append(action[1]) 33 AssertionError:
请注意,
有预期步骤的线性序列
步骤可能会有所不同(有些正在删除,有些正在添加到锅中)
我们设法通过一个函数/生成器来完成所有这些工作 – 不需要使用复杂的类或类似的结构。
运行总计
我们可以使用生成器来跟踪发送给它的值的总数。
任何时候,我们添加一个数字,input和总数的计数返回(有效的前一刻input发送到它)。
from collections import namedtuple RunningTotal = namedtuple("RunningTotal", ["n", "total"]) def runningtotals(n=0, total=0): while True: delta = yield RunningTotal(n, total) if delta: n += 1 total += delta if __name__ == "__main__": nums = [9, 8, None, 3, 4, 2, 1] bookeeper = runningtotals() print bookeeper.next() for num in nums: print num, bookeeper.send(num)
输出将如下所示:
RunningTotal(n=0, total=0) 9 RunningTotal(n=1, total=9) 8 RunningTotal(n=2, total=17) None RunningTotal(n=2, total=17) 3 RunningTotal(n=3, total=20) 4 RunningTotal(n=4, total=24) 2 RunningTotal(n=5, total=26) 1 RunningTotal(n=6, total=27)