web-dev-qa-db-fra.com

Comment vérifier si un objet est un objet générateur en python?

En python, comment puis-je vérifier si un objet est un objet générateur?

Essayer cela -

>>> type(myobject, generator)

donne l'erreur -

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'generator' is not defined

(Je sais que je peux vérifier si l'objet a une méthode next pour qu'il soit un générateur, mais je veux un moyen permettant de déterminer le type de n'importe quel objet, pas seulement des générateurs.)

127
Pushpak Dagade

Vous pouvez utiliser GeneratorType à partir de types:

>>> import types
>>> types.GeneratorType
<class 'generator'>
>>> gen = (i for i in range(10))
>>> isinstance(gen, types.GeneratorType)
True
188
utdemir

Vous voulez dire les fonctions du générateur? utilisation inspect.isgeneratorfunction .

MODIFIER:

si vous voulez un objet générateur, vous pouvez utiliser inspect.isgenerator comme indiqué par JAB dans son commentaire.

33
mouad

Je pense qu'il est important de faire la distinction entre les fonctions de générateur et les générateurs ( résultat de la fonction générateur):

>>> def generator_function():
...     yield 1
...     yield 2
...
>>> import inspect
>>> inspect.isgeneratorfunction(generator_function)
True

l'appel à generator_function ne donnera pas de résultat normal, il n'exécutera même pas de code dans la fonction elle-même, le résultat sera un objet spécial appelé générateur:

>>> generator = generator_function()
>>> generator
<generator object generator_function at 0x10b3f2b90>

donc ce n'est pas une fonction de générateur, mais un générateur:

>>> inspect.isgeneratorfunction(generator)
False

>>> import types
>>> isinstance(generator, types.GeneratorType)
True

et la fonction générateur n'est pas générateur:

>>> isinstance(generator_function, types.GeneratorType)
False

juste pour une référence, l'appel réel du corps de fonction se fera en consommant le générateur, par exemple:

>>> list(generator)
[1, 2]

Voir aussi In python existe-t-il un moyen de vérifier si une fonction est une "fonction générateur" avant de l'appeler?

16
Robert Lujo

Le inspect.isgenerator la fonction est correcte si vous voulez rechercher des générateurs purs (c'est-à-dire des objets de la classe "générateur"). Cependant, il renverra False si vous vérifiez, par exemple, un izip itérable. Une autre façon de vérifier un générateur généralisé consiste à utiliser cette fonction:

def isgenerator(iterable):
    return hasattr(iterable,'__iter__') and not hasattr(iterable,'__len__')
11
Luca Sbardella
>>> import inspect
>>> 
>>> def foo():
...   yield 'foo'
... 
>>> print inspect.isgeneratorfunction(foo)
True
2
Corey Goldberg

Je sais que je peux vérifier si l'objet a une méthode suivante pour qu'il soit un générateur, mais je veux un moyen de déterminer le type de n'importe quel objet, pas seulement des générateurs.

Ne fais pas ça. C'est simplement une très, très mauvaise idée.

Au lieu de cela, procédez comme suit:

try:
    # Attempt to see if you have an iterable object.
    for i in some_thing_which_may_be_a_generator:
        # The real work on `i`
except TypeError:
     # some_thing_which_may_be_a_generator isn't actually a generator
     # do something else

Dans le cas peu probable où le corps de la boucle for a également TypeErrors, il y a plusieurs choix: (1) définir une fonction pour limiter la portée des erreurs, ou (2) utilisez un bloc try imbriqué.

Ou (3) quelque chose comme ça pour distinguer tous ces TypeError qui flottent autour.

try:
    # Attempt to see if you have an iterable object.
    # In the case of a generator or iterator iter simply 
    # returns the value it was passed.
    iterator = iter(some_thing_which_may_be_a_generator)
except TypeError:
     # some_thing_which_may_be_a_generator isn't actually a generator
     # do something else
else:
    for i in iterator:
         # the real work on `i`

Ou (4) corrigez les autres parties de votre application pour fournir des générateurs de manière appropriée. C'est souvent plus simple que tout cela.

2
S.Lott

Si vous utilisez un serveur Web tornado ou similaire, vous avez peut-être constaté que les méthodes serveur sont en fait des générateurs et non des méthodes. Cela rend difficile d'appeler d'autres méthodes car le rendement ne fonctionne pas à l'intérieur de la méthode et vous devez donc commencer à gérer des pools d'objets générateurs chaînés. Une méthode simple pour gérer des pools de générateurs chaînés consiste à créer une fonction d'aide telle que

def chainPool(*arg):
    for f in arg:
      if(hasattr(f,"__iter__")):
          for e in f:
             yield e
      else:
         yield f

Maintenant, écrit des générateurs enchaînés tels que

[x for x in chainPool(chainPool(1,2),3,4,chainPool(5,chainPool(6)))]

Produit une sortie

[1, 2, 3, 4, 5, 6]

C'est probablement ce que vous voulez si vous cherchez à utiliser des générateurs comme alternative de thread ou similaire.

1
user6830669