Verhalten von Pythons "yield"

8

Ich lese über das Schlüsselwort yield in Python und versuche zu verstehen, wie dieses Beispiel ausgeführt wird:

%Vor%

Die Ausgabe ist:

%Vor%

Es sieht so aus, als würde die Ausbeute den angegebenen Wert zurückgeben und die Funktion bis zum Ende (in einem parallelen Thread vielleicht) fortsetzen. Ist mein Verständnis korrekt?

Wenn Sie das beantworten könnten, ohne "Generatoren" zu erwähnen, wäre ich dankbar, weil ich versuche, eins nach dem anderen zu verstehen.

    
Tom Brito 09.09.2011, 14:06
quelle

6 Antworten

20

Sie können sich das so vorstellen, als würde die Funktion yield s einfach "pausieren", wenn sie auf yield stößt. Wenn Sie es das nächste Mal aufrufen, wird es nach dem yield fortgesetzt und behält den Status bei, in dem es sich befand, als es verlassen hat.

    
carlpett 09.09.2011, 14:17
quelle
6

Nein, es gibt nur einen einzigen Thread.

Jede Iteration der for-Schleife führt Ihre countFrom -Funktion aus, bis sie etwas ergibt oder zurückkehrt. Nach der Ausbeute wird der Rumpf der for-Schleife erneut ausgeführt und dann, wenn eine neue Iteration beginnt, nimmt die Funktion countFrom genau dort wieder auf, wo sie aufgehört hat, und läuft erneut, bis sie nachgibt (oder zurückkehrt).

Diese modifizierte Version Ihres Beispiels wird hilfreich dabei helfen, die Ausführung des Pfades klarer zu machen.

%Vor%

Ausgabe

%Vor%     
David Heffernan 09.09.2011 14:18
quelle
4
___ answer7363045 ___

Sie können sich das so vorstellen, als würde die Funktion yield s einfach "pausieren", wenn sie auf .next() stößt. Wenn Sie es das nächste Mal aufrufen, wird es nach dem .next() fortgesetzt und behält den Status bei, in dem es sich befand, als es verlassen hat.

    
___ answer7363056 ___

Nein, es gibt nur einen einzigen Thread.

Jede Iteration der for-Schleife führt Ihre .next() -Funktion aus, bis sie etwas ergibt oder zurückkehrt. Nach der Ausbeute wird der Rumpf der for-Schleife erneut ausgeführt und dann, wenn eine neue Iteration beginnt, nimmt die Funktion .next() genau dort wieder auf, wo sie aufgehört hat, und läuft erneut, bis sie nachgibt (oder zurückkehrt).

Diese modifizierte Version Ihres Beispiels wird hilfreich dabei helfen, die Ausführung des Pfades klarer zu machen.

%Vor%

Ausgabe

%Vor%     
___ answer7363078 ___

Die Funktion yield wird nicht in einem parallelen Thread ausgeführt. Was passiert hier, wenn die %code% -Konstruktion nach dem nächsten Wert fragt, wird die Funktion ausgeführt, bis sie eine %code% -Anweisung trifft. Wenn der nächste Wert danach benötigt wird, setzt die Funktion die Ausführung dort fort, wo sie unterbrochen wurde.

Und während Sie gebeten haben, "Generatoren" nicht zu erwähnen, sind sie so eng mit %code% verbunden, dass es nicht wirklich Sinn macht, darüber getrennt zu sprechen. Was Ihre %code% -Funktion tatsächlich zurückgibt, ist ein "Generator-Objekt". Sie gibt dieses Objekt unmittelbar nach dem Aufruf zurück, so dass der Funktionskörper überhaupt nicht ausgeführt wird, bis etwas (z. B. %code% -loop) Werte vom Generator mit seiner Methode %code% anfordert.

    
___ answer7362962 ___

Die Yield-Anweisung speichert den Wert, den Sie erhalten, bis diese Funktion erneut aufgerufen wird. Wenn Sie also diese Funktion (mit einem Iterator) aufrufen, wird die Funktion ein anderes Mal ausgeführt und Sie erhalten den Wert. Der Punkt ist, dass es weiß, wo es beim letzten Mal aufgehört hat.

    
___ qstntxt ___

Ich lese über das Schlüsselwort %code% in Python und versuche zu verstehen, wie dieses Beispiel ausgeführt wird:

%Vor%

Die Ausgabe ist:

%Vor%

Es sieht so aus, als würde die Ausbeute den angegebenen Wert zurückgeben und die Funktion bis zum Ende (in einem parallelen Thread vielleicht) fortsetzen. Ist mein Verständnis korrekt?

Wenn Sie das beantworten könnten, ohne "Generatoren" zu erwähnen, wäre ich dankbar, weil ich versuche, eins nach dem anderen zu verstehen.

    
___ tag123python ___ Python ist eine dynamische und stark typisierte Programmiersprache, die die Usability betont. Zwei ähnliche, aber größtenteils inkompatible Versionen von Python sind weit verbreitet (2 und 3). Wenn Sie eine versionsspezifische Python-Frage haben, sollten Sie die Tags [python-2.7] oder [python-3.x] zusätzlich zum Tag [python] verwenden. Wenn Sie eine Python-Variante wie jython, pypy, iron-python usw. verwenden, kennzeichnen Sie diese bitte entsprechend. ___ answer7363207 ___

Python wird ausgeführt, bis es auf %code% trifft, und stoppt dann und stoppt die Ausführung. Es läuft nicht weiter. Beim nächsten Aufruf von %code%

wird "nach" gedrückt

Das ist leicht zu sagen, ohne auf Generatoren Bezug zu nehmen, aber Tatsache ist, dass Ertrag und Generator untrennbar miteinander verbunden sind. Um es wirklich zu verstehen, müssen Sie sie als das gleiche Thema betrachten.

Es ist einfach, sich selbst zu zeigen, dass das, was ich (und andere) gesagt habe, wahr ist, wenn man mit dem Generator auf eine manuellere Weise von deinem Beispiel aus arbeitet.

Eine Funktion, die %code% s anstelle von %code% ing tatsächlich einen Generator zurückgibt. Sie können diesen Generator dann konsumieren, indem Sie %code% aufrufen. Sie sind verwirrt, weil Ihre Schleife sich um alles kümmert, was im Hintergrund für Sie ist.

Hier ist es mit den Interna geöffnet:

%Vor%     
___ tag123yield ___ yield ist (1) ein Schlüsselwort, das die Erstellung von Generatorfunktionen erleichtert, (2) eine Ruby-Anweisung, um die Kontrolle von einer Coroutine auf eine andere zu übertragen ___ qstnhdr ___ Verhalten von Pythons "yield" ___
redShadow 09.09.2011 14:29
quelle
1

Die Funktion countfrom wird nicht in einem parallelen Thread ausgeführt. Was passiert hier, wenn die for -Konstruktion nach dem nächsten Wert fragt, wird die Funktion ausgeführt, bis sie eine yield -Anweisung trifft. Wenn der nächste Wert danach benötigt wird, setzt die Funktion die Ausführung dort fort, wo sie unterbrochen wurde.

Und während Sie gebeten haben, "Generatoren" nicht zu erwähnen, sind sie so eng mit yield verbunden, dass es nicht wirklich Sinn macht, darüber getrennt zu sprechen. Was Ihre countfrom -Funktion tatsächlich zurückgibt, ist ein "Generator-Objekt". Sie gibt dieses Objekt unmittelbar nach dem Aufruf zurück, so dass der Funktionskörper überhaupt nicht ausgeführt wird, bis etwas (z. B. for -loop) Werte vom Generator mit seiner Methode .next() anfordert.

    
shang 09.09.2011 14:20
quelle
0

Die Yield-Anweisung speichert den Wert, den Sie erhalten, bis diese Funktion erneut aufgerufen wird. Wenn Sie also diese Funktion (mit einem Iterator) aufrufen, wird die Funktion ein anderes Mal ausgeführt und Sie erhalten den Wert. Der Punkt ist, dass es weiß, wo es beim letzten Mal aufgehört hat.

    
Ted 09.09.2011 14:11
quelle
0

Python wird ausgeführt, bis es auf yield trifft, und stoppt dann und stoppt die Ausführung. Es läuft nicht weiter. Beim nächsten Aufruf von countfrom

wird "nach" gedrückt

Das ist leicht zu sagen, ohne auf Generatoren Bezug zu nehmen, aber Tatsache ist, dass Ertrag und Generator untrennbar miteinander verbunden sind. Um es wirklich zu verstehen, müssen Sie sie als das gleiche Thema betrachten.

Es ist einfach, sich selbst zu zeigen, dass das, was ich (und andere) gesagt habe, wahr ist, wenn man mit dem Generator auf eine manuellere Weise von deinem Beispiel aus arbeitet.

Eine Funktion, die yield s anstelle von return ing tatsächlich einen Generator zurückgibt. Sie können diesen Generator dann konsumieren, indem Sie next aufrufen. Sie sind verwirrt, weil Ihre Schleife sich um alles kümmert, was im Hintergrund für Sie ist.

Hier ist es mit den Interna geöffnet:

%Vor%     
Finn 09.09.2011 14:30
quelle

Tags und Links