2017-07-28 6 views
0

私は、区切り文字列を区切り文字列のリストからkwargs型辞書オブジェクトを生成する関数に一般化されたジェネレータ関数を持っています。関数のkwargsマッピングを生成するジェネレータオブジェクト

私は、別のジェネレータ関数の引数としてkwargs型辞書を使いたいと思います。

def line_from_file_generator(file_name): 

    with open(file_name) as text_file: 
     for line in text_file: 
      yield line 

def map_delimited_lines_to_kwargs(lines, delimiter, kwarg_index_map): 

    for line in lines: 

     kwargs = {} 
     args = line.strip().split(delimiter) 

     for kwarg, index in kwarg_index_map.items(): 
      kwargs[kwarg] = args[index] 

     yield kwargs 


def edge_generator(source_node_name, destination_node_name, weights): 

    for line in lines: 
     yield Edge(source_node_name, destination_node_name, weights) 


lines = line_from_file_generator('mit_map.txt') 
kwarg_index_map = {'source_node_name': 0, 'destination_node_name': 1, 'weights': 2} 
kwarg_collection = map_delimited_lines_to_kwargs(lines, ' ', kwarg_index_map) 
edges = edge_generator(**kwargs_collection) 

私は今理解:**ここ

を発電機ではない私の現在、壊れたコードであり、マッピングである必要があります後しかし、私はメッセージ

edge_generator()の引数を取得しますなぜこれが間違っているのですか(ジェネレータはシーケンスの一種であり、マッピング(展開することができる)ではありません)。

私が作成した抽象概念を維持しながら、これを回避することはできますか?コードは何ですか?最後の行を以下に変更しようとしましたが、kwargsジェネレータを反復処理できず、すべての辺が同じ引数で生成されます。

+0

、あなたの 'map_delimited_lines_to_kwargs()'単に*リターン*シングルkwargsからは、ループ後のdict必要があります(もちろん、ループの前にそれを初期化する)のではなく、ループを1時間ごとに得。 – jasonharper

+0

@jasonharper - はい、あなたは正しいと思います。これは、物事を大幅に簡素化します!私はジェネレータの機能で船に乗ったと思う。彼らを使うのは初めてです... – Jinglesting

+0

@jasonharper、先にエッジを生成するためにkwargsをすべて実現しなければならないので、後でグラフを作成するためにエッジを使用するときジェネレータを使用する利点を失います時間の。私はこれを行う別の方法を見つけましたが、答えとして投稿します – Jinglesting

答えて

0

これは私が動作させる方法です。関数定義でEdgeジェネレータの引数を拡張しようとするのではなく、単にkwargsジェネレータ全体を渡し、Edgeジェネレータ本体のkwargsジェネレータにループを追加し、エッジを作成するときに引数を拡張しました。

def line_from_file_generator(file_name): 

    with open(file_name) as text_file: 
     for line in text_file: 
      yield line 


def kwargs_from_delimited_strings_generator(lines, delimiter, kwarg_index_map): 

    for line in lines: 

     kwargs = {} 
     args = line.strip().split(delimiter) 

     for kwarg, index in kwarg_index_map.items(): 
      kwargs[kwarg] = args[index] 

     yield kwargs 


def edge_generator(kwargs_collection): 

    for kwargs in kwargs_collection: 
     yield Edge(**kwargs) 


lines_from_file = line_from_file_generator('mit_map.txt') 
kwarg_index_map = {'source_node_name': 0, 'destination_node_name': 1, 
        'weights': 2} 
kwargs_from_delimited_strings = kwargs_from_delimited_strings_generator(
            lines_from_file, ' ', kwarg_index_map) 
edges_from_kwargs = edge_generator(kwargs_from_delimited_strings) 
0

あなたのプログラムを変更する方法は次のとおりです。

私はできるだけ長く**演算子を使用して遅延することに注意してください。実際には、私はコンクリートが1つしかなければ使用しません。dict

edge_generatorは、引数に反復することに注意してください。linesではありません。とにかくlinesがどこから来たのか分からない。

ジェネレータのチェーンが保持されていることに注意してください。 list()コンストラクタが最終ジェネレータに適用されるまで、完全な辺の集合は構築されません。一見

def Edge(source_node_name, destination_node_name, weights): 
    '''Testing version of Edge()''' 
    return '{}/{}/{}'.format(source_node_name, destination_node_name, weights) 

def line_from_file_generator(file_name): 
    with open(file_name) as text_file: 
     for line in text_file: 
      yield line 

def map_delimited_lines_to_kwargs(lines, delimiter, kwarg_index_map): 
    for line in lines: 
     kwargs = {} 
     args = line.strip().split(delimiter) 

     for kwarg, index in kwarg_index_map.items(): 
      kwargs[kwarg] = args[index] 

     yield kwargs 

def edge_generator(edge_attribute_dicts): 
    for attribute_dict in edge_attribute_dicts: 
     yield Edge(**attribute_dict) 

lines = line_from_file_generator('mit_map.txt') 
kwarg_index_map = { 
    'source_node_name': 0, 
    'destination_node_name': 1, 
    'weights': 2} 
kwargs_collection = map_delimited_lines_to_kwargs(lines, ' ', kwarg_index_map) 
edges = edge_generator(kwargs_collection) 
print(list(edges)) 
関連する問題