La valeur de retour (générateur) d'une fonction qui combine finally et yield ne doit pas être passée directement à next

Il existe un code comme celui-ci.

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)

Lorsque vous appelez yielder, si vous dites for y dans yielder (): f (y), la sortie sera

yielder setup
text
yielder teardown

Cependant, si vous l'utilisez pour que next soit appelé une seule fois (* 3 des 4 méthodes décrites à la fin à l'exclusion de la première),

yielder setup
text

devenir de cette façon. le démontage n'est pas appelé. En ajoutant enfin, le teardown sera appelé.

Cependant, lors de l'appel de cette fonction, avec for y in yielder_with_finally (): f (y) or y = yielder_with_finally (); f (next (y))

yielder setup
text
yielder teardown

Cependant, si vous appelez t = next (yielder_with_finally ()); f (t) ou f (next (yielder_with_finally ())),

yielder setup
yielder teardown
text

Cela devient un ordre d'exécution inattendu. Il s'est comporté de la même manière dans CPython2 / 3. Cependant, si le démontage est exécuté en appelant next une seule fois, il sera difficile à déboguer (dans IPython, etc.), il se peut donc qu'il ne soit pas possible de l'utiliser de cette manière en premier lieu. ** Ce peut être une bonne idée de ne pas utiliser finalement pour le démontage lors de la cession. ** **

Le dispositif de rendement de pytest est implémenté de manière à pouvoir être tourné deux fois correctement, ce problème ne se produit donc pas. https://docs.pytest.org/en/latest/_modules/_pytest/fixtures.html


Dans PyPy, avec ou sans enfin, le comportement était le même que sans enfin dans CPython.

Je l'ai vérifié avec Ruby, mais le comportement n'a pas changé avec ou sans assurer (similaire à 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

La valeur de retour (générateur) d'une fonction qui combine finally et yield ne doit pas être passée directement à next
[Linux] [C / C ++] Comment obtenir la valeur d'adresse de retour d'une fonction et le nom de fonction de l'appelant
[C / C ++] Passez la valeur calculée en C / C ++ à une fonction python pour exécuter le processus et utilisez cette valeur en C / C ++.
[Python] Un programme pour trouver le nombre de pommes et d'oranges qui peuvent être récoltées
Lors de l'incrémentation de la valeur d'une clé qui n'existe pas
Note addictive: max (max (list)) ne doit pas être utilisé lors de la maximisation de la valeur d'un tableau à deux dimensions
Comment créer un wrapper qui préserve la signature de la fonction à envelopper
Pourquoi la fonction d'activation doit être une fonction non linéaire
Valeur de retour de quit () -Y a-t-il quelque chose retourné par la "fonction qui termine tout"?
Une solution au problème que les fichiers contenant [et] ne sont pas répertoriés dans glob.glob ()
[Python of Hikari-] Chapitre 06-02 Fonction (argument et valeur de retour 1)
#Une fonction qui renvoie le code de caractère d'une chaîne de caractères
Implémentation d'un générateur en utilisant Python> link> yield et next ()> yield
L'histoire selon laquelle la valeur de retour de tape.gradient () était None
La valeur de meta lors de la spécification d'une fonction sans valeur de retour avec Dask dataframe s'applique
J'ai aussi essayé d'imiter la fonction monade et la monade d'état avec le générateur en Python
Comment supprimer les avertissements "L'indentation pep8 n'est pas un multiple de quatre" et "La variable dans la fonction doit être en minuscules" de Pycharm
J'ai fait une fonction pour vérifier le modèle de DCGAN
Une histoire sur l'écriture d'AWS Lambda et de devenir un peu accro aux valeurs par défaut des arguments Python
[Python] Le rôle de l'astérisque devant la variable. Divisez la valeur d'entrée et affectez-la à une variable
Une raison simple pour laquelle la valeur de retour de round (2.675,2) est de 2,67 en python (elle devrait être de 2,68 en réalité ...)