4

間に構造化データを渡すノードのネットワークがあります。私のサブ問題には、この分岐があります-ノードの線形シーケンス:

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]1 つのスレッド (入れ子になっている可能性があります) と、もう 1 つのスレッド (入れ子になっている可能性があります) では、 と の間で[n3, n4]データがパイプされます。ケース: この方法でブランチをグループ化したい非線形ノード グラフがあるかもしれません。n2n3

node計算状態を保持するクラスである必要があります

contextとの実装はどのpipe(context, node)ように見えるでしょうか? または、別の方法で解決できる場合、何かヒントはありますか?

yield fromPython 3.3 (PEP380)で私のケースを何らかの方法で助けることができますか?

4

1 に答える 1

2

任意の数の関数 (または callable) を構成することだけが必要な場合は、モジュールのドキュメントのcompose_multレシピを使用してください。functional

それを使用するソリューション:

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 関数を抽出する を使用します。

ただし、開始したばかりのジェネレーターには許可されないことに注意してください(値を受け取るにsendは a の時点にある必要があるため)。これは、最初の反復でジェネレーターにダミー値を設定し、 に送信する前のある時点でそれらを進めるyieldなど、自分で処理する必要があるものです。または、ノードを通常の callable として保持することもできます。yieldchain_nodes

イテレータを 1 ステップ進める必要がある場合:next(izip(*nodes[1:]))

于 2012-04-12T12:32:01.033 に答える