Python-在各种使用者中消耗一个生成器 [英] Python -- consuming one generator inside various consumers
问题描述
我有一个供各种消费者使用的发电机.后者每个都可以从生成器中获取不同的项目,因此我不能仅使用一个大的for循环来处理所有项目.我想要的是完全消耗发电机.怎么办?
I have a generator to be consumed by various consumers. Each of the latter can take different items from the generator, so I can't just use one big for-loop to take care of all the items. What I want is to completely consume the generator. How can it be done?
# -*- coding: utf-8 -*-
MEALS = ['Oysters', 'Consommé', 'Lamb', 'Rice', 'Sirloin','Banana', 'Pastry']
def server():
for n in MEALS:
yield n
def client(course, take):
meal = []
for _ in range(take):
some_meal = next(course)
meal.append(some_meal)
return meal
if __name__ == '__main__':
#print("Available meals: ", list(MEALS))
course = server()
try:
while True:
meal = client(course, 3)
print("First client: ", meal)
meal = client(course, 2)
print("Second client: ", meal)
except StopIteration:
pass
当前输出:
First client: ['Oysters', 'Consommé', 'Lamb']
Second client: ['Rice', 'Sirloin']
但是甜点在哪里?
预期输出:
First client: ['Oysters', 'Consommé', 'Lamb']
Second client: ['Rice', 'Sirloin']
First client: ['Banana', 'Pastry']
更新可以接受的解决方案如下,其中对返回列表进行了测试,只是我简化了示例代码(client
中可以有很多next
语句).我现在需要的是一种方法,只要第一个StopIteration
升高,就可以从client
函数返回.因此,我添加了关于在退出第一个函数时退出函数的最佳方法的后续问题StopIteration .
UPDATE The accepted solution below with the added test on the returned list is OK except that I oversimplified the example code (There can be many next
statements in client
). What I now need is a way to return from the client
function as soon as the first StopIteration
is raised. So I added a follow-up question about the best way to exit a function upon hitting the first StopIteration.
推荐答案
在while
循环的第二次迭代中,server
生成器仅产生2个项目,并且client()
函数将触发StopIteration
尝试获取3个元素时发生异常.
In the second iteration of the while
loop, the server
generator only has 2 more items to yield, and the client()
function will trigger the StopIteration
exception when it tries to get 3 elements.
您需要在client()
函数中处理StopIteration
:
def client(course, take):
meal = []
for _ in range(take):
try:
some_meal = next(course)
meal.append(some_meal)
except StopIteration:
pass
return meal
现在,客户端将处理StopIteration
,您将不得不以不同的方式处理while
循环;如果client()
不返回元素,则您的server
必须为空:
Now that a client will handle the StopIteration
, you'll have to handle the while
loop differently; if a client()
doesn't return elements your server
must've been empty:
while True:
meal = client(course, 3)
if not meal:
break
print("First client: ", meal)
meal = client(course, 2)
print("Second client: ", meal)
if not meal:
break
您在这里缺少Python标准库中的一些技巧.您可以使用iter()
重新实现server
:
You are missing a few tricks from the Python standard library here. You can reimplement your server
with iter()
:
def server():
return iter(MEALS)
,您可以使用 itertools.islice()
来处理您的客户:
and you could use itertools.islice()
to handle your client:
from itertools import islice
def client(course, take):
return list(islice(course, take))
这篇关于Python-在各种使用者中消耗一个生成器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!