Iterierbares Objekt mit mehrere Werten

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
gstueb
User
Beiträge: 5
Registriert: Freitag 24. Juli 2009, 14:25
Wohnort: Langenau

Hallo,

ich habe eine Textdatei, in der sich Bildbeschreibungen und die dazugehörigen URLs befinden:

katze, http://www.blabla.de/katze.jpg
hund, http://www.blabla.de/hund.jpg

Ich hätte nun gerne ein Unterprogramm, dem ich nur den Dateinamen übergebe, und von dem ich die Bildbeschreibungen und URLs zurückerhalte, so dass ich sie weiterbearbeiten kann.

Ich bin nun absoluter Anfänger in python, aber ich dachte mir, dass hier ein iterierbares Objekt sinnvoll wäre, wie es z.B. bei http://openbook.galileocomputing.de/pyt ... 8c937ad98d beschrieben ist.

Hier mal ein Stück Code (als Idee), den ich habe, der aber nicht funktioniert, vor allem, weil ich ja mehrere Werte, und nicht nur einen zurückgeben will.

Code: Alles auswählen

class Bilder(object): 
    def __init__(self, dateiname): 
        self.Max = -1
        self.Url = {}
        eingabe = open(dateiname, 'r')
        for zeile in eingabe:
                self.Url.append(zeile)
 
    def __iter__(self): 
        self.N = 0 
        return self 
 
    def next(self): 
        if self.N < self.MaxN: 
            self.N += 1 
            return self.Url[self.N]
        else: 
            raise StopIteration
Wie müsste ich vorgehen, damit ich letztendlich nur noch folgenden Code bräuchte:

Code: Alles auswählen

for b in Bilder("blabla.txt"): 
        print(b.Beschreibung)
        print(b.Url)
Danke schonmal ;-)
Gregor
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Python kann bereits über Dateien iterieren. Da musst du das Rad nicht umbedingt neu erfinden:

Code: Alles auswählen

with open('blabla.txt', 'r') as fobj:
    for line in fobj:
        description, url = line.split(', ')
        # etc.
Grüße
Gerrit


PS: Es gibt Kritik am "OpenBook" die man kennen sollte.
BlackJack

@gstueb: Das in dem Galileo Openbook Iterator-Klassen gezeigt werden ist eine nette Veranschaulichung was eine Klasse erfüllen muss, um als Iterator durchzugehen, aber in der Praxis braucht man sehr selten eigene Klassen für Iteratoren. Die erstellt man seit dem es ``yield`` gibt, viel einfacher und kürzer mit Generatorfunktionen.

An dem ersten Beispiel der Fibonacci-Zahlen ist das Rücksetzen des internen Zustands auch ungewöhnlich. Sowas sollte man auf jeden Fall sehr deutlich dokumentieren, weil das ein sehr überraschendes Verhalten ist. Für gewöhnlich geben Iteratoren -- im Gegensatz zu "iterables" -- hier einfach nur sich selbst zurück, ohne irgendwas zu machen. Wenig später bemerken die Autoren das anhand eines anderen Beispiels ja selbst. Allerdings ist das Beispiel mit dem Anfordern eine Iterators von einem Dateiobjekt schlicht falsch! Das setzt nicht wie behauptet den Dateizeiger auf den Anfang zurück, also lösen sie da ein Problem was es so gar nicht gibt. :roll:

Für solche Beispiele ist es natürlich auch wichtig zu zeigen, dass die `next()`-Methode irgendwann eine `StopIteration`-Ausnahme auslösen kann, aber bei einem Iterator über eine unendliche Folge, macht es auch Sinn tatsächlich einen unendlichen Iterator zu schreiben. Wer nur einen Teil davon braucht kann zum Beispiel `islice()` oder `takewhile()` aus dem `itertools`-Modul verwenden.

`Fibonacci2` macht als Klasse nicht mehr viel Sinn, weil das eigentlich eine Funktion ist. Es würde letztlich auf diese nette kleine Funktion hinauslaufen:

Code: Alles auswählen

def fibonacci():
    a, b = 0, 1
    while True:
        a, b = b, a + b
        yield a
Und für Dein Beispiel sind es auch nicht mehr Zeilen:

Code: Alles auswählen

def iter_images(filename):
    with open(filename) as lines:
        for line in lines:
            description, url = line.split(',', 1)
            yield description, url.strip()
Zu verwenden mit:

Code: Alles auswählen

for description, url in iter_images('blah.txt'):
    # do something with `description` and `url`...
Antworten