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

__iter__ ohne yield

Beitragvon Mad-Marty » 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")
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Re: __iter__ ohne yield

Beitragvon Leonidas » 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

Beitragvon Mad-Marty » 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).
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » 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

Beitragvon Mad-Marty » 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.
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » 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

Beitragvon str1442 » 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

Beitragvon Trundle » 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)

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder