Seite 1 von 1
Generator ok?
Verfasst: Montag 12. Dezember 2011, 13:40
von mzh
Liebes Forum, hab mich etwas mit Generators beschäftigt und ein Anwendungsbeispiel versucht damit umzusetzen. Aus einer Textdatei werden Parameter und Werte gelesen und in einer Dictionary gespeichert.
Code: Alles auswählen
'inp_file.inp':
# Setup parameters
foo_len 2000.0 # foo length [nm]
foo_rad 10.0 # foo radius [nm]
# Other parameters
bar_len 100.0 # bar length [nm]
bar_rad 1.1 # bar radius [nm]
Dann wird eine Funktion aus den Parametern befüttert und eine Zahl ausgegeben. '#' sollten Kommentare darstellen, die mir erlauben das Parameterfile etwas zu dokumentieren.
Hier der Generator:
Code: Alles auswählen
def get_input(input_file):
with open(input_file) as input_data:
for line in input_data:
if len(line.split()) > 2:
param, value = line.split()[0], line.split()[1]
yield param, value
def generate_input(input_file):
params = {}
for line in get_input(input_file):
if line[0] != '#':
params[line[0]] = line[1]
return params
di=generate_input('inp_file.inp')
for k,v in di.items():
print k,v
Die Print Ausgabe ist dazu da um zu sehen wie das ankommt. Wie würdet ihr das weiter verpythonifizieren?
Danke für feedback.
Re: Generator ok?
Verfasst: Montag 12. Dezember 2011, 14:19
von derdon
Du rufst in get_input drei mal line.split auf, das kann man auf einen Aufruf reduzieren. Außerdem kannst du auch da wieder sequence unpacking statt indexing anwenden, sieht schöner aus. Sequence unpacking kannste auch in generate_input verwenden.
Re: Generator ok?
Verfasst: Montag 12. Dezember 2011, 14:37
von JonasR
Ich denke aus den beiden Funktionen kannst du auch eine machen
Btw wieso 'generate_input' wenn es nur den Generator aufruft? Sollte der Generator nicht eher so heißen?

Re: Generator ok?
Verfasst: Montag 12. Dezember 2011, 14:45
von /me
mzh hat geschrieben:Code: Alles auswählen
def generate_input(input_file):
params = {}
for line in get_input(input_file):
if line[0] != '#':
params[line[0]] = line[1]
return params
Das schreit ja förmlich nach einer dict comprehension
Code: Alles auswählen
return {param:value for (param, value) in get_input(input_file) if param != '#'}
Re: Generator ok?
Verfasst: Montag 12. Dezember 2011, 18:28
von Hyperion
/me hat geschrieben:
Das schreit ja förmlich nach einer dict comprehension
Code: Alles auswählen
return {param:value for (param, value) in get_input(input_file) if param != '#'}
Gibt es das auch unter Python 2.x? Ich hatte immer im Kopf, dass das eine der Neuerungen von Python 3 ist... (was der OP offensichtlich verwendet)
Re: Generator ok?
Verfasst: Montag 12. Dezember 2011, 18:38
von cofi
Wie gut, dass man das testen kann
Code: Alles auswählen
Python 2.7.2+ (default, Nov 30 2011, 19:22:03)
Type "copyright", "credits" or "license" for more information.
IPython 0.11 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: {key : 42 for key in range(5)}
Out[1]: {0: 42, 1: 42, 2: 42, 3: 42, 4: 42}
Re: Generator ok?
Verfasst: Montag 12. Dezember 2011, 18:41
von Hyperion
cofi hat geschrieben:Wie gut, dass man das testen kann
Ich hab im Moment nur einen Laptop mit Python 3.2 drauf

Außerdem hatte ich in der Doku mal im Tutorial geguckt. In Kapitel 5.5 hab ich in der Doku zu 2.7 kein Wort dazu gefunden - bei 3.2 schon

Re: Generator ok?
Verfasst: Montag 12. Dezember 2011, 18:46
von sma
Die dict-comprehension gibt es auch in Python 2.7.
Ich würde übrigens die Kommentare bereits in get_input() ausfiltern und finde auch nicht so schön, dass der Dateiname "input_file" heißt, was suggeriert, dass das ein file-Objekt ist. Stattdessen würde ich lieber ein file-Objekt übergeben, denn das ist der generischere Fall. Schließlich kann ich bei split auch die Variante aus dem re-Modul benutzen, dann habe ich nicht so viele Leerzeichen vor dem Wert stehen.
Hier ist mein Vorschlag:
Code: Alles auswählen
import re
def get_input(f):
for line in f:
line = line.split("#")[0].strip()
if line:
yield re.split("\\s+", line, 1)
def generate_input(f):
return {k: v for k, v in get_input(f)}
from StringIO import StringIO
print generate_input(StringIO.StringIO("""
# Setup parameters
foo_len 2000.0 # foo length [nm]
foo_rad 10.0 # foo radius [nm]
# Other parameters
bar_len 100.0 # bar length [nm]
bar_rad 1.1 # bar radius [nm]
"""))
Stefan
Re: Generator ok?
Verfasst: Montag 12. Dezember 2011, 19:17
von /me
Hyperion hat geschrieben:Gibt es das auch unter Python 2.x? Ich hatte immer im Kopf, dass das eine der Neuerungen von Python 3 ist... (was der OP offensichtlich verwendet)
Nein, seit kurzem ist es Python 2.7 statt 2.6. Python 3 kommt bei mir erst, wenn Django damit läuft.
Re: Generator ok?
Verfasst: Montag 12. Dezember 2011, 20:28
von DasIch
@sma: Ein dict(get_input(f)) hätte es auch getan
