2016-03-31 14 views
3

Ich benutze Python 3.5, um eine Reihe von Generatoren zu erstellen, um eine Reihe geöffneter Dateien zu analysieren, um Daten aus diesen Dateien auszuwählen, um ein Objekt zu erstellen, das ich plane später exportieren. Ich analysierte ursprünglich die Gesamtheit aller Dateien und erstellte eine Liste von Wörterbuchobjekten, bevor ich eine Analyse durchführte, aber dieser Prozess würde manchmal bis zu 30 Sekunden dauern, und da ich nur mit jeder Zeile jeder Datei nur einmal arbeiten muss, I Stellen Sie es eine große Gelegenheit dar, einen Generator zu verwenden. Ich habe jedoch das Gefühl, dass ich konzeptionell etwas mit Generatoren vermisse und vielleicht die Veränderlichkeit von Objekten innerhalb eines Generators.Änderbarkeit von Python-Generator-Ausdrücke versus Listen- und Wörterbuch-Verständnis

Meine ursprüngliche Code, der eine Liste der Wörterbücher macht geht wie folgt:

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] 

Und ich Zugriff auf die in der Liste durch den Aufruf:

>>>parsers['definitions'] 

Und es funktioniert erwartet als eine Liste der Wörterbücher Rückkehr . Wenn ich diese Liste in einen Generator umwandele, passiert allerlei Seltsamkeit.

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) 

Und ich nenne es durch die Verwendung:

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

Ausführen dieses Codes liefert einen Index aus Bereichsfehler. Der Hauptunterschied, den ich zwischen den beiden Code-Segmenten sehen kann, ist, dass in der Listenverständnis-Version python die Liste aus der Datei konstruiert und weitergeht, ohne dass die Comprehensions-Variablen zur späteren Verwendung gespeichert werden müssen.

Umgekehrt müssen im Generatorausdruck die im Generator definierten Variablen mit dem Generator gespeichert werden, da sie jeden nachfolgenden Aufruf des Generators später in meinem Code bewirken. Ich denke, dass vielleicht die Variablen innerhalb des Generators einen Namensraum mit den anderen Generatoren teilen, die mein Code erzeugt, und so hat jeder Generator ein fehlerhaftes Verhalten, basierend auf dem zuletzt ausgeführten Generatorausdruck, und setzt daher die Werte der Variablen zuletzt.

Ich freue mich über irgendwelche Gedanken über den Grund für dieses Problem!

+0

Können Sie die vollständige Rückverfolgung buchen? Es könnte hilfreich sein. . . – mgilson

Antwort

3

Ich nehme an, dass das Problem ist, wenn Sie die Wörterbücher erstellen.

attributes[dataset][i] 

Beachten Sie, dass mit der Liste Version, dataset was ist dataset an dieser bestimmten Windung der for Schleife war. Doch mit dem Generator, wird dieser Ausdruck nicht bis nach die for-Schleife ausgewertet abgeschlossen hat, so dataset den Wert des letzten-Datensatz aus der files.items() Schleife haben ...

Hier eine super einfache Demo ist hoffentlich, dass näher auf das Problem:

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

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

Bitte beachte, dass wir immer [3, 3, 3] bekommen, denn wenn wir die Werte aus dem Generator nehmen, wird der Wert von a3 ist.

+0

Das ist es!Danke für die Hilfe, die mitgelieferte Demo hat mir sehr dabei geholfen, mich mit dem Thema zu beschäftigen. Ich bekam ein inkonsistentes Verhalten, bei dem manchmal jedes Wörterbuch korrekt angezeigt wurde, weil ich über ein Wörterbuch iterierte, und so würden meine Generatoren funktionieren, wenn eine ausreichend lange Attributliste als letztes Element aufgerufen wurde (Wörterbücher werden natürlich nicht geordnet). Ich habe auch nie gesehen, dass der Unterstrich außerhalb des Interpreters verwendet wurde, ich werde versuchen, das in Zukunft zu integrieren, um im Online-Speicher zu sparen, danke. – CameronCairns