Iterator und yield

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
maxip
User
Beiträge: 61
Registriert: Dienstag 11. März 2008, 09:43

Hallo,

ich bin neu in Python, kenne aber schon PHP, Perl, C (auch POSIX), C++ und vor allem Java.

Nun hab ich eine Verstaendninsfrage:

Warum funktioniert folgende klasse nicht wie erwartet:

Code: Alles auswählen

import csv

class CSVIterator(object):
    """Iterates over a CSV-File"""
    def __init__(self, csv_file, csv_file_flags = "rb"):
        self.file = csv_file
        self.flags = csv_file_flags
    def __iter__(self):
        self.reader = csv.reader(open(self.file, self.flags))
        return self
    def next(self):
        for row in self.reader:
            yield row
        else:
            raise StopIteration
Wenn man for row in CSVIterator("dat.csv"): print row macht, dann bekommt man immer als Ausgabe Generator Object und die zugehoerige Adresse.

Lese ich vorher alle rows ein, erzeuge einen internen Zaehler und gebe sie dann nach und nach in next() zurueck, so funktioniert es.

Mir ist nicht ganz klar, warum yield hier nicht funktioniert.

Vielleicht kann mir das jmd. erklaeren :)

Vielen Dank

ciao Daniel

P.S. bis jetzt bin ich echt begeistert von Python :)

Hier noch der Code, wie ich es jetyt geloest habe (ist das Optimal so ?)

Code: Alles auswählen

import csv

class CSVIterator(object):
    """Iterates over a CSV-File"""
    def __init__(self, csv_file, csv_file_flags = "rb"):
        self.file = csv_file
        self.flags = csv_file_flags
    def __iter__(self):
        self.reader = csv.reader(open(self.file, self.flags))
        self.rows = []
        for single_row in self.reader:
            self.rows.append(single_row)
        self.i = 0
        return self
    def next(self):
        if(self.i < len(self.rows)):
            self.i = self.i + 1
            return self.rows[self.i - 1]
        else:
            raise StopIteration
BlackJack

Wenn ``yield`` in einer Funktion vorkommt, dann ist das eine Generatorfunktion, d.h. die Funktion gibt einen Generator zurück. Jedesmal wenn Du `next()` aufrufst bekommst Du so einen Generator.

Was Du da machst ist alles superumständlich. `csv.reader()` gibt schon einen Iterator oder zumindest ein "iterable" zurück. Deine Klasse ist also nur viel toter Ballast.
maxip
User
Beiträge: 61
Registriert: Dienstag 11. März 2008, 09:43

Stimmt :)

Hab das Modul komplett geloescht.

Ich wollte nur eine Art iteratable-interface haben, aber wie du bereits gesagt hast, ist csv.reader ja schon iteratable :)

viele dank
Antworten