Kann ich Fehler in einem Listenverständnis fangen, um sicher zu sein, alle Listenelemente zu schleifen

Ich habe ein Listenverständnis, das eine Liste filtert:

l = [obj for obj in objlist if not obj.mycond()] 

Aber die Objektmethode mycond () kann eine Ausnahme heben, die ich abfangen muss. Ich muss alle Fehler am Ende der Schleife sammeln, um zu zeigen, welches Objekt irgendwelche Probleme verursacht hat und gleichzeitig möchte ich sicher sein, alle Listenelemente zu schleifen.

Meine Lösung war:

 errors = [] copy = objlist[:] for obj in copy: try: if (obj.mycond()): # avoiding to touch the list in the loop directly objlist.remove(obj) except MyException as err: errors = [err] if (errors): #do something return objlist 

In diesem Beitrag ( Wie lösche ich Listenelemente beim Radfahren der Liste selbst ohne doppelte es ) Ich frage, ob es eine bessere Methode zu Zyklus Vermeidung der Liste Duplikat.

Die Community antwortet mir, um Platzänderungsänderungen zu vermeiden und ein Listenverständnis zu verwenden, das anwendbar ist, wenn ich das Ausnahmeproblem ignoriere.

Gibt es eine alternative Lösung in Ihrer Sicht? Kann ich Exception auf diese Weise mit Listenverständnissen verwalten? In dieser Art von Situation und mit großen Listen (was muss ich groß sein?) Ich muss eine andere Alternative finden?

    4 Solutions collect form web for “Kann ich Fehler in einem Listenverständnis fangen, um sicher zu sein, alle Listenelemente zu schleifen”

    Ich würde eine kleine Hilfsfunktion benutzen:

     def f(obj, errs): try: return not obj.mycond() except MyException as err: errs.append((obj, err)) errs = [] l = [obj for obj in objlist if f(obj, errs)] if errs: emiterrorinfo(errs) 

    Beachten Sie, dass auf diese Weise Sie errs alle fehlerhaften Objekte und die spezifische Ausnahme, die jedem von ihnen entspricht, so dass die Diagnose genau und vollständig sein kann; objlist wie die, die Sie benötigen, und Ihre objlist noch intakt für mögliche weitere Verwendung. Es wurde keine obj benötigt, noch Änderungen an obj Klasse und die Gesamtstruktur des Codes ist sehr einfach.

    Ein paar kommentare:

    Zuerst wird die Liste der Verständnis-Syntax [expression for var in iterable] eine Kopie erstellen. Wenn Sie keine Kopie der Liste erstellen möchten, dann verwenden Sie den Generatorausdruck (expression for var in iterable) .

    Wie arbeiten Generatoren? Im Wesentlichen, indem man next(obj) auf das Objekt wiederholt next(obj) bis eine GeneratorExit Ausnahme next(obj) wird.

    Basierend auf Ihrem ursprünglichen Code, scheint es, dass Sie noch die gefilterte Liste als Ausgabe benötigen.

    So können Sie das mit wenig Leistungsverlust emulieren:

     l = [] for obj in objlist: try: if not obj.mycond() l.append(obj) except Exception: pass 

    Allerdings könntest du das alles mit einer Generatorfunktion neu konstruieren:

     def FilterObj(objlist): for obj in objlist: try: if not obj.mycond() yield obj except Exception: pass 

    Auf diese Weise können Sie sicher iterieren, ohne eine Liste in der Zwischenzeit zu unterschulen:

     for obj in FilterObj(objlist): obj.whatever() 

    Sie könnten eine Methode von obj definieren, die obj.mycond () anruft, aber auch die Ausnahme fängt

     class obj: def __init__(self): self.errors = [] def mycond(self): #whatever you have here def errorcatcher(): try: return self.mycond() except MyException as err: self.errors.append(err) return False # or true, depending upon what you want l = [obj for obj in objlist if not obj.errorcatcher()] errors = [obj.errors for obj in objlist if obj.errors] if errors: #do something 

    Anstatt die Liste zu kopieren und Elemente zu entfernen, beginnen Sie mit einer leeren Liste und fügen Sie die Mitglieder nach Bedarf hinzu. Etwas wie das:

     errors = [] newlist = [] for obj in objlist: try: if not obj.mycond(): newlist.append(obj) except MyException as err: errors.append(err) if (errors): #do something return newlist 

    Die Syntax ist nicht so hübsch, aber es wird mehr oder weniger das Gleiche tun, dass das Listenverständnis ohne unnötige Umzüge erfolgt.

    Hinzufügen oder Entfernen von Elementen zu oder von irgendwo anders als das Ende einer Liste wird langsam sein, denn wenn Sie etwas entfernen, muss es durch jedes Element, das nach ihm kommt und subtrahieren ein von seinem Index zu gehen, und die gleiche Sache für das Hinzufügen von etwas außer es Ich muss den Index hinzufügen. Aktualisiere die Position aller Elemente danach.

    Python ist die beste Programmiersprache der Welt.