31 votes

Dans python est-il un moyen de vérifier si une fonction est une «fonction générateur» avant de l'appeler?

Disons que j'ai deux fonctions:

def foo():
  return 'foo'

def bar():
  yield 'bar'

La première est une fonction normale, et la seconde est une fonction de générateur. Maintenant, je veux écrire quelque chose comme ceci:

def run(func):
  if is_generator_function(func):
     gen = func()
     gen.next()
     #... run the generator ...
  else:
     func()

Ce sera une simple mise en œuvre d' is_generator_function() ressemble? À l'aide de l' types forfait je peux tester si gen est un générateur, mais je veux le faire avant d'invoquer func().

Maintenant, considérons le cas suivant:

def goo():
  if False:
     yield
  else:
     return

Une invocation de l' goo() sera de retour d'un générateur. Je présume que le python analyseur sait que l' goo() de la fonction yield, et je me demande s'il est possible d'obtenir cette information facilement.

Merci!

35voto

Corey Goldberg Points 15625
<pre><code></code><ul> <li>Nouveau dans Python version 2.6</li> </ul></pre>

12voto

Greg Hewgill Points 356191

En fait, je me demande à quel point une telle hypothèse `` serait vraiment utile. Considérer:

Qu'est-ce qui devrait revenir pour et ? retourne un `````` générateur, mais n'est pas un lui-même, et pourrait retourner un générateur ou pourrait ne pas.

7voto

Alex Martelli Points 330805
>>> def foo():
...   return 'foo'
... 
>>> def bar():
...   yield 'bar'
... 
>>> import dis
>>> dis.dis(foo)
  2           0 LOAD_CONST               1 ('foo')
              3 RETURN_VALUE        
>>> dis.dis(bar)
  2           0 LOAD_CONST               1 ('bar')
              3 YIELD_VALUE         
              4 POP_TOP             
              5 LOAD_CONST               0 (None)
              8 RETURN_VALUE        
>>>

Comme vous le voyez, la différence essentielle est que le pseudo-code d' bar contiendra au moins un YIELD_VALUE opcode. Je recommande l'utilisation de l' dis (module de rediriger sa sortie à un StringIO instance et la vérification de sa getvalue, bien sûr) parce que cela vous donne une mesure de la robustesse sur le bytecode -- changements -- l'exacte des valeurs numériques des opcodes va changer, mais le démonté valeur symbolique va rester assez stable;-).

0voto

Damien Points 45

J'ai mis en place un décorateur qui accroche sur la fonction décorée retourné / valeur cédée. Son basique va:

Il fonctionne parce que la fonction de décorateur est inconditionnellement appelé: c'est la valeur de retour qui est testé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X