[PYTHON] Der Rückgabewert (Generator) einer Funktion, die endlich und Ausbeute kombiniert, darf nicht direkt an next übergeben werden

Es gibt Code wie diesen.

def yielder():
    #try:
    print('yielder setup')
    yield 'text'
    #finally:
    print('yielder teardown')

def yielder_with_finally():
  try:
    print('yielder setup')
    yield 'text'
  finally:
    print('yielder teardown')

def f(text):
  print(text)

Wenn Sie beim Aufruf von yielder "für y in yielder (): f (y)" sagen, wird die Ausgabe ausgeführt

yielder setup
text
yielder teardown

Wenn Sie es jedoch so verwenden, dass next nur einmal aufgerufen wird (* 3 der 4 am Ende beschriebenen Methoden mit Ausnahme der ersteren),

yielder setup
text

so werden. Teardown wird nicht aufgerufen. Durch das endgültige Hinzufügen wird Teardown aufgerufen.

Beim Aufrufen dieser Funktion jedoch mit "für y in yielder_with_finally (): f (y)" oder "y = yielder_with_finally (); f (next (y))"

yielder setup
text
yielder teardown

Wenn Sie jedoch "t = next (yielder_with_finally ()); f (t)" oder "f (next (yielder_with_finally ())") aufrufen,

yielder setup
yielder teardown
text

Es wird eine unerwartete Ausführungsreihenfolge. In CPython2 / 3 verhielt es sich ähnlich. Wenn das Herunterfahren jedoch nur durch einmaliges Aufrufen von next ausgeführt wird, ist das Debuggen schwierig (in IPython usw.), sodass es möglicherweise überhaupt nicht möglich ist, es auf diese Weise zu verwenden. ** Es kann eine gute Idee sein, beim Nachgeben nicht endgültig zum Abreißen zu verwenden. ** ** **

Die Ertragsvorrichtung von pytest ist so implementiert, dass sie zweimal richtig gedreht werden kann, so dass dieses Problem nicht auftritt. https://docs.pytest.org/en/latest/_modules/_pytest/fixtures.html


In PyPy war das Verhalten mit oder ohne endgültig das gleiche wie ohne endgültig in CPython.

Ich habe es mit Ruby überprüft, aber das Verhalten hat sich nicht mit oder ohne Gewähr geändert (ähnlich wie bei PyPy).

def yielder()
  return to_enum(:yielder) if !block_given?
  #begin
    puts('yielder setup')
    yield 'text'
  #ensure
    puts('yielder teardown')
  #end
end

def yielder_with_ensure()
  return to_enum(:yielder_with_ensure) if !block_given?
  begin
    puts('yielder setup')
    yield 'text'
  ensure
    puts('yielder teardown')
  end
end

def f(text)
  puts(text)
end

Recommended Posts

Der Rückgabewert (Generator) einer Funktion, die endlich und Ausbeute kombiniert, darf nicht direkt an next übergeben werden
[Linux] [C / C ++] So ermitteln Sie den Wert der Rücksprungadresse einer Funktion und den Funktionsnamen des Aufrufers
[C / C ++] Übergeben Sie den in C / C ++ berechneten Wert an eine Python-Funktion, um den Prozess auszuführen, und verwenden Sie diesen Wert in C / C ++.
[Python] Ein Programm, um die Anzahl der Äpfel und Orangen zu ermitteln, die geerntet werden können
Beim Inkrementieren des Werts eines Schlüssels, der nicht vorhanden ist
Suchthinweis: max (max (Liste)) darf nicht verwendet werden, wenn der Wert eines zweidimensionalen Arrays maximiert wird
So erstellen Sie einen Wrapper, der die Signatur der zu umschließenden Funktion beibehält
Warum die Aktivierungsfunktion eine nichtlineare Funktion sein muss
Rückgabewert von quit () - Gibt es etwas, das von der "Funktion, die alles beendet" zurückgegeben wird?
Eine Lösung für das Problem, dass Dateien mit [und] nicht in glob.glob () aufgeführt sind
[Python of Hikari-] Kapitel 06-02 Funktion (Argument und Rückgabewert 1)
#Eine Funktion, die den Zeichencode einer Zeichenfolge zurückgibt
Implementieren eines Generators mit Python> Link> Yield und next ()> Yield
Die Geschichte, dass der Rückgabewert von tape.gradient () None war
Der Wert von meta beim Angeben einer Funktion ohne Rückgabewert mit Dask dataframe gilt
Ich habe auch versucht, die Funktionsmonade und die Zustandsmonade mit dem Generator in Python nachzuahmen
So unterdrücken Sie Pycharms Warnungen "pep8-Einrückung ist kein Vielfaches von vier" und "Variable in Funktion sollte Kleinbuchstaben sein"
Ich habe eine Funktion erstellt, um das Modell von DCGAN zu überprüfen
Eine Geschichte über das Schreiben von AWS Lambda und ein wenig Abhängigkeit von den Standardwerten von Python-Argumenten
[Python] Die Rolle des Sterns vor der Variablen. Teilen Sie den Eingabewert und weisen Sie ihn einer Variablen zu
Ein einfacher Grund, warum der Rückgabewert von round (2.675,2) in Python 2,67 beträgt (in Wirklichkeit sollte er 2,68 betragen ...)