Generator ok?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
mzh
User
Beiträge: 295
Registriert: Dienstag 3. März 2009, 15:27
Wohnort: ZH

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.
[url=http://www.proandkon.com]proandkon.com[/url]
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

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.
JonasR
User
Beiträge: 251
Registriert: Mittwoch 12. Mai 2010, 13:59

Ich denke aus den beiden Funktionen kannst du auch eine machen :D
Btw wieso 'generate_input' wenn es nur den Generator aufruft? Sollte der Generator nicht eher so heißen? :P
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

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 != '#'}
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

/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)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Wie gut, dass man das testen kann :P

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}
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

cofi hat geschrieben:Wie gut, dass man das testen kann :P
Ich hab im Moment nur einen Laptop mit Python 3.2 drauf :-P
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 ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

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
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

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.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

@sma: Ein dict(get_input(f)) hätte es auch getan ;)
Antworten