Verwendung des Generators send () innerhalb einer for-Schleife

8

Ich habe die Graph-Traversierung als eine Generatorfunktion implementiert, die den besuchten Knoten liefert.

Manchmal muss der Benutzer der Traversierungsfunktion mitteilen, dass die Kanten, die von einem bestimmten Knoten ausgehen, nicht befolgt werden sollten; Um dies zu unterstützen, überprüft der Traversal den zurückgesendeten Wert (mit dem Generator send() method), und wenn es True ist, betrachtet er den Knoten als ein Blatt für Traversierungszwecke.

Das Problem ist, dass die einfachste Benutzerschleife ziemlich lang ist:

%Vor%

Gibt es eine Möglichkeit, dies zu verbessern?

Ich dachte, so etwas sollte funktionieren:

%Vor%

aber ich fühle, dass mir das Wissen über eine Python-Syntax fehlt.

    
max 25.04.2016, 08:47
quelle

4 Antworten

3

Ich sehe keine Möglichkeit, dies in einer normalen for -Schleife zu tun. Sie könnten jedoch einen anderen Generator erstellen, der einen anderen Generator iteriert und dabei eine "follow-function" verwendet, um zu ermitteln, ob dem aktuellen Element gefolgt werden soll. Dadurch werden die komplizierten Teile Ihres Codes in eine separate Funktion eingekapselt.

%Vor%     
tobias_k 25.04.2016, 09:11
quelle
2

Um den Client-Code zu vereinfachen, könnten Sie einen gewöhnlichen bsf() Generator verwenden und das node.isleaf Attribut darin überprüfen:

%Vor%

Der Nachteil ist, dass node veränderbar ist. Oder Sie übergeben eine gemeinsame Datenstruktur, die Blattknoten verfolgt: leaf[node] = process(node) , wobei leaf dictionary in bfs() früher übergeben wird.

Wenn Sie .send() method explizit verwenden möchten; Sie müssen mit StopIteration umgehen. Siehe PEP 479 - Ändern der StopIteration-Behandlung in Generatoren . Sie könnten es in einer Hilfsfunktion verstecken:

%Vor%

Beispiel:

%Vor%     
jfs 26.04.2016 13:09
quelle
1

Ich sehe das nicht als häufigen Anwendungsfall, betrachte dies als den ursprünglichen Generator:

%Vor%

Wenn der Wert von should_break immer auf Basis eines Funktionsaufrufs mit x berechnet wird, dann schreibe den Generator einfach so:

%Vor%

Allerdings denke ich normalerweise an den Code, der die generierten Werte so verarbeitet, dass sie in die Schleife geschrieben werden (sonst, was ist der Sinn, überhaupt eine Schleife zu haben?)

Was Sie wirklich zu tun scheinen, ist einen Generator zu erstellen, bei dem der Aufruf der __next__ -Methode wirklich send(process(LAST_VALUE)) impliziert, was mit einer Klasse implementiert werden kann:

%Vor%

Allerdings wird dies immer noch nicht so häufig verwendet. Ich wäre völlig in Ordnung mit einer while -Schleife, obwohl ich den .send -Aufruf an die Spitze gesetzt hätte:

%Vor%

Und Sie könnten das in ein try: ... except StopIteration:pass einbinden, obwohl ich finde, dass es einfach besser ist, auf einen Fehler zu warten, um es mit einem Kontextmanager auszudrücken:

%Vor%     
Tadhg McDonald-Jensen 26.04.2016 11:45
quelle
0

Ich habe festgestellt, dass meine Frage eine einzeilige Antwort gehabt hätte, indem ich die erweiterte "continue" -Anweisung verwendet habe, die in frühere Version von PEP 342 :

%Vor%

Während jedoch PEP 342 akzeptiert wurde, wurde dieses spezielle Feature nach diese Juni 2005 Diskussion zwischen Raymond und Guido:

  

Raymond Hettinger hat gesagt:

     
    

Lassen Sie mich als starke -1 für "EXPR fortfahren" aufzeichnen. Das     for-loop ist unser grundlegendstes Konstrukt und leicht zu verstehen     gegenwärtige Form. Das gleiche gilt für "weiter" und "break" was     haben den zusätzlichen Vorteil einer Lernkurve nahe Null für Menschen     Migration von anderen Sprachen.

         

Jeder Drang, diese grundlegenden Aussagen zu komplizieren, sollte ernst genommen werden     überprüft und gehalten zu hohen Standards der Klarheit, Erklärbarkeit,     Offensichtlichkeit, Nützlichkeit und Notwendigkeit. IMO, es versagt die meisten von denen     Tests.

         

Ich würde mich nicht darauf freuen, im Tutorial "EXPR fortführen" zu erklären     und denke, es würde sich als Anti-Feature herausstellen.

  
     

[...] Das korrekte Argument gegen "EXPR fortfahren" ist das dort   sind noch keine Anwendungsfälle; wenn es einen guten Anwendungsfall gäbe, die Erklärung   würde leicht folgen.

     

Guido

Wenn Python-Core-Entwickler seither ihre Meinung über den Nutzen von erweitertem "continue" geändert haben, könnte dies vielleicht in einem zukünftigen PEP wieder eingeführt werden. Aber angesichts eines nahezu identischen Anwendungsfalls, wie er in dieser Frage bereits im zitierten Thread diskutiert wurde und nicht überzeugend gefunden wurde, erscheint dies unwahrscheinlich.

    
max 01.05.2016 01:45
quelle