首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用生成器形成多个管道?

如何使用生成器形成多个管道?
EN

Stack Overflow用户
提问于 2017-08-29 01:05:11
回答 3查看 619关注 0票数 4

我正在使用python,并试图找到一种优雅地将多个生成器链接在一起的方法。例如,有一个根生成器,它提供某种类型的数据,每个值都像级联一样传递给它的“子对象”,而级联又可以修改它们接收到的对象。我可以走这条路:

代码语言:javascript
复制
for x in gen1:
    gen2(x)
    gen3(x)

但它既丑陋又不优雅。我在想一种更实用的做事方式。

EN

回答 3

Stack Overflow用户

发布于 2017-08-29 01:10:50

管道可能看起来更像这样:

代码语言:javascript
复制
for x in gen3(gen2(gen1())):
    print x

例如:

代码语言:javascript
复制
for i, x in enumerate(range(10)):
    print i, x

在Python中,没有一种方法可以分叉(或"tee")管道。如果您想要多个管道,则必须复制它们:gen2(gen1())gen3(gen1())

票数 1
EN

Stack Overflow用户

发布于 2017-08-29 01:19:44

Dave Beazley gave this example in a talk he did in 2008。目标是对Apache web服务器日志中传输的数据字节数进行求和。假设日志格式如下:

代码语言:javascript
复制
81.107.39.38 -  ... "GET /ply/ HTTP/1.1" 200 7587
81.107.39.38 -  ... "GET /favicon.ico HTTP/1.1" 404 133
81.107.39.38 -  ... "GET /admin HTTP/1.1" 403 -

传统的(非生成器)解决方案可能如下所示:

代码语言:javascript
复制
with open("access-log") as wwwlog:
    total = 0
    for line in wwwlog:
        bytes_as_str = line.rsplit(None,1)[1]
        if bytes_as_str != '-':
            total += int(bytes_as_str)
print("Total: {}".format(total))

使用生成器表达式的生成器管道可以可视化为:

代码语言:javascript
复制
access-log => wwwlog => bytecolumn => bytes => sum() => total

可能看起来像这样:

代码语言:javascript
复制
with open("access-log") as wwwlog:
    bytecolumn = (line.rsplit(None,1)[1] for line in wwwlog)
    bytes = (int(x) for x in bytecolumn if x != '-')
print("Total: {}".format(sum(bytes)))

Dave Beazley的幻灯片和更多的例子可以在on his website上找到。His later presentations elucidate this further

如果不知道你到底想做什么,就很难说得更多了,所以我们可以评估你所做的每件事是否都需要一个自定义的生成器(生成器表达式/理解在许多事情上都可以很好地工作,而不需要声明生成器函数)。

票数 0
EN

Stack Overflow用户

发布于 2017-08-29 03:15:03

下面是一个简明的例子:

代码语言:javascript
复制
def negate_nums(g):
    for x in g:
        yield -x

def square_nums(g):
    for x in g:
        yield x ** 2

def half_num(g):
    for x in g:
        yield x / 2.0

def compose_gens(first_gen,*rest_gens):
    newg = first_gen(compose_gens(*rest_gens)) if rest_gens else first_gen
    return newg

for x in compose_gens(negate_nums,square_nums,half_num,range(10)):
    print(x)

在这里,您正在组合生成器,以便在最后的compose_gens调用中从右向左调用它们。您可以通过反转args将其更改为管道。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45924087

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档