__iter__ ohne 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
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

Donnerstag 12. Februar 2009, 10:19

Hi,

wenn ein object in seiner __iter__ nur ein raise StopIteration() hat ... wird dies als normale Exception nach oben durchgereicht.

Erst mit einem Dummy-yield funktioniert es wie gewünscht.
Muss die __iter__ method als Generator (durch yield) definiert sein?

Wie erreiche ich das Verhalten des unteren Dummys ohne das Hässliche 'if'?

Dieses Object lässt sich nicht iterieren ohne Exception

Code: Alles auswählen

class Dummy(object):
   def __iter__(self):
      raise StopIteration("dummy intended not to iterate")
Dieses hingegen schon:

Code: Alles auswählen

class Dummy(object):
   def __iter__(self):
      if False:
         yield True
      raise StopIteration("dummy intended not to iterate")
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Donnerstag 12. Februar 2009, 10:26

Mad-Marty hat geschrieben:Muss die __iter__ method als Generator (durch yield) definiert sein?
Nein, sie muss aber einen Iterator zurückgeben. Du hast schon recht, eine ``StopIteration`` wäre logisch, aber die ist wie du siehst nur in Generatoren nützlich.

Meine Lösung ohne ein ``if`` sähe so aus:

Code: Alles auswählen

class Dummy(object):
    def __iter__(self):
        return iter(list())
Persönlich finde ich die leere Liste nicht so gut gelungen, aber normalerweise macht man Objekte nicht-``iterable`` indem man ``__iter__`` schlicht nicht definiert ;)
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

Donnerstag 12. Februar 2009, 10:38

Persönlich finde ich die leere Liste nicht so gut gelungen, aber normalerweise macht man Objekte nicht-``iterable`` indem man ``__iter__`` schlicht nicht definiert Wink
Naja ich finde Objekte sollten (sofern sinnvoll), schon iterierbar sein, einfach weil es sich super in die Sprache integriert.

(Und der Dummy ist mehr fürs Testen in dem Fall).
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Donnerstag 12. Februar 2009, 10:40

Mad-Marty hat geschrieben:Naja ich finde Objekte sollten (sofern sinnvoll), schon iterierbar sein, einfach weil es sich super in die Sprache integriert.
Ja, aber wenn du das iterieren durch so Tricks "abschalten" willst, klingt es so als würde es eben nicht sinnvoll sein über dieses Objekt zu iterieren.
Aber das ist natürlich schwer abzuschätzen, wenn man deinen Code nicht kennt.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

Donnerstag 12. Februar 2009, 12:40

Eine Factory verarbeitet empfangene Daten zu unterschiedlichen datensets.
Es wird explizit damit gerechnet das manche daten nicht konvertiert oder verwendet werden können.

Die empfangenen Daten sind sofern richtig, iterierbar bzw generatoren.
Für ungültige Daten muss auch ein Dummy objekt her, was bei verwendung eben nichts iteriert (da keine gültigen Daten) und somit eben nur ein paar counter und stats erhöht.

Es soll also bewusst keine Exceptions geben bei ungültigen Daten und diese Datensätze sollen sich in der weiteren chain verhalten wie gültige in bezug auf statistik, allerdings eben keinen verwendbaren inhalt anbieten bei iteration.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Donnerstag 12. Februar 2009, 13:05

Ok, das scheint mehr oder weniger ok zu sein. Nunja, eine funktionierende Lösung ist oben gepostet, was wesentlich eleganteres fällt mir nicht mehr ein :)
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Donnerstag 12. Februar 2009, 17:11

Code: Alles auswählen

class NotIterable(object):
     def next(self):
          raise StopIteration()

class Dummy(object):
     def __iter__(self):
          return NotIterable()
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Donnerstag 12. Februar 2009, 17:20

@str1442: Iterator-Objekte sollten auch eine `__iter__`-Methode haben, die einfach das Objekt selbst wieder zurückgibt, damit man auch über das Iterator-Objekt iterieren kann.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
Antworten