【问题标题】:How to compose iterators?如何组合迭代器?
【发布时间】:2012-04-24 17:05:23
【问题描述】:

我有一个节点网络,在它们之间传递结构化数据。对于我的子问题,我们有这个分支 - 节点的线性序列:

nodes = [source, n1, n2, n3, n4]

第一个节点是一个生成器,每个其他节点都从输入节点获取值并提供输出值。当前的实现是简单的 get() 从管道和 put() 到管道,每个节点都有单独的线程(这是有原因的)。我想把它改成yield-ing 迭代器。

我想以以下方式进行评估(如果我们认为节点是可调用的):

for result in n4(n3(n2(n1(source()))):
    print result

我想像这样构建评估上下文:

context = src
for node in nodes[1:]:
    context = pipe(context, node)

for result in context:
    print result

限制:

我仍然希望能够单独使用节点 - 不是嵌套的,通过其他方式管道数据,因为节点可能位于单独的线程中。示例:[source, n1,n2] 在一个线程中(可能是嵌套的),[n3, n4] 在另一个线程中(可能是嵌套的),数据在 n2n3 之间通过管道传输。案例:可能有一个非线性节点图,我想以这种方式对分支进行分组。

node 必须是一个类来保存计算状态

contextpipe(context, node) 的实现可能是什么样的?或者如果可以用不同的方式解决,你有什么提示吗?

Python 3.3 中的yield from (PEP380) 可以以任何方式帮助我的案例吗?

【问题讨论】:

    标签: python function functional-programming iterator generator


    【解决方案1】:

    如果您只想组合任意数量的函数(或可调用对象),请使用 functional 模块文档中的 compose_mult recipe

    使用它的解决方案:

    from functional import compose, foldr, partial
    from itertools  import imap
    compose_mult = partial(reduce, compose) 
    chain_nodes = lambda nodes: imap(compose_mult(nodes[1:]), nodes[0])
    chain_gen_nodes = lambda nodes: imap(compose_mult((g.send for g in nodes[1:])), nodes[0])
    
    
    # equivalent not as a one-liner
    #def chain_nodes(nodes):
    #    source = nodes[0]
    #    composed_nodes = compose_mult(nodes[1:])
    #    return (composed_nodes(x) for x in source)
    

    如果节点是接受输入的生成器(通过send),则使用chain_gen_nodes,它会提取它们的发送函数。

    但是请注意,不允许将send 发送到刚刚启动的生成器(因为它必须位于yield 的位置才能接收值)。这是您必须自己处理的事情,例如让您的生成器yield 在第一次迭代时设置一个虚拟值,并在将它们发送到chain_nodes 之前的某个时间点推进它们。或者您可以将节点保留为普通的可调用对象。

    如果您确实需要将迭代器推进一步:next(izip(*nodes[1:]))

    【讨论】:

    • 这就是我在我的问题中写的——这就是我想要实现的原则。问题是,节点列表在计算之前是未知的。这就是为什么我将节点列为数组nodes = [...]
    • @Stiivi 这不是你写的。但是,我已经更新了我的答案。
    • 我很抱歉不够清楚,并感谢您的建议 - 似乎是有用的解决方案。您认为可以使用标准 python 库来完成吗(“不”或“太复杂”也可以接受简单的答案)?我想避免更多的依赖(在这种情况下是functional)。
    • @Stiivi reducepartial 存在于标准库中。你可以很容易地推出自己的compose 版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-20
    • 2016-03-26
    • 2018-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多