我有一个发电机供各种消费者使用。后者中的每一个都可以从生成器中获取不同的项目,因此我不能只使用一个大的for循环来处理所有项目。我想要的是完全消耗发电机。怎么办呢?
# -*- 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']
UPDATE 下面接受的解决方案在返回的列表中添加了测试,但我已经过度简化了示例代码(next
中可能有很多client
个语句) 。我现在需要的是在第一个client
被引发后立即从StopIteration
函数返回的方法。所以我添加了关于the best way to exit a function upon hitting the first StopIteration的后续问题。
答案 0 :(得分:4)
在while
循环的第二次迭代中,server
生成器只有2个项可以产生,client()
函数会触发StopIteration
异常试图获得3个元素。
您需要处理StopIteration
函数中的client()
:
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
必须为空:
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标准库的一些技巧。您可以使用server
重新实现iter()
:
def server():
return iter(MEALS)
您可以使用itertools.islice()
来处理您的客户:
from itertools import islice
def client(course, take):
return list(islice(course, take))