2016-03-31 6 views
3

私は計画したオブジェクトを構築するためにそれらのファイルからデータを選択するために、開いたファイルのセットを解析するためにPython 3.5を使用して、後でエクスポートする。私はもともと各ファイル全体を解析し、分析を行う前に辞書オブジェクトのリストを作成していましたが、このプロセスは時には30秒かかることがあり、各ファイルの各行を1回だけ処理する必要があるため、その発電機を使用する絶好の機会となっています。しかし、私は、発電機を概念的に、そしておそらく発電機内の物体の変更可能性を見逃していると感じています。次のように辞書のリストを作るPython Generatorの表現とリストと辞書の理解の比較:入れ子になっている辞書の奇妙さ

私の元のコードは行く:

parsers = {} 
# iterate over files in the file_name file to get their attributes 
for dataset, data_file in files.items(): 
    # Store each dataset as a list of dictionaries with keys that 
    # correspond to the attributes of that dataset 
    parsers[dataset] = [{attributes[dataset][i]: value.strip('~') 
         for i, value in enumerate(line.strip().split('^'))} 
         for line 
         in data_file] 

そして私は呼び出すことでリストにアクセス:

>>>parsers['definitions'] 

そして予想通り、それは辞書のリストを返す動作します。しかし、このリストをジェネレータに変換すると、あらゆる種類の奇妙なことが起こります。

parsers = {} 
# iterate over files in the file_name file to get their attributes 
for dataset, data_file in files.items(): 
    # Store each dataset as a list of dictionaries with keys that 
    # correspond to the attributes of that dataset 
    parsers[dataset] = ({attributes[dataset][i]: value.strip('~') 
         for i, value in enumerate(line.strip().split('^'))} 
         for line 
         in data_file) 

そして私は使用してそれを呼び出す:範囲エラーのうちのインデックスを返します

>>> next(parsers['definitions']) 

をこのコードを実行します。

2つのコードセグメントの主な違いは、リストの解説バージョンでは、ファイルからリストを作成し、後で使用するための解説変数を格納する必要がなくなります。

逆に、ジェネレータ表現では、ジェネレータ内で定義された変数はジェネレータに格納する必要があります。これは後でジェネレータの呼び出しをコードの後に​​実行するためです。おそらく、ジェネレータ内部の変数は、私のコードが作成する他のジェネレータと名前空間を共有しているので、各ジェネレータは最後に実行されたジェネレータ式に基づいて不規則な振る舞いをするため、変数の値を最後に設定すると考えています。

私はこの問題の理由を考えています。

+0

完全なトレースバックを投稿できますか?それは役に立つかもしれません。 。 。 – mgilson

答えて

3

辞書を作成するときに問題があると想定します。リストバージョンで、datasetdatasetforループの特定のターンにあったものは何でもあることを

attributes[dataset][i] 

注意。しかし、発電機でループが完了したため後、そうdatasetfiles.items()ループから最後のデータセットの値を持つことになりますまで、その式が評価されていません...

はここで、超簡単なデモですそれがうまくいけば問題について詳しく説明:私たちは発電機からの値をとるとき、aの値が3あるので、我々は常に[3, 3, 3]を得る

results = [] 
for a in [1, 2, 3]: 
    results.append(a for _ in range(3)) 

for r in results: 
    print(list(r)) 

注意。

+0

それだけです!助けてくれてありがとう、提供されたデモは、私の頭をこの問題の周りで包み込むように手伝ってくれました。私は、辞書を繰り返していたために各辞書が正しく表示されることがあり、最後の要素(辞書は当然順序付けされていない)として十分に長い属性リストが呼び出されたときに動作するという矛盾した振る舞いをしていました。また、私は通訳者の外で使用されたアンダースコアを見たことがない、私はラインスペースで保存するために、将来それを組み込むことを試みるかもしれない、ありがとう。 – CameronCairns

関連する問題