Python-在各种使用者中消耗一个生成器 [英] Python -- consuming one generator inside various consumers

查看:88
本文介绍了Python-在各种使用者中消耗一个生成器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个供各种消费者使用的发电机.后者每个都可以从生成器中获取不同的项目,因此我不能仅使用一个大的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆