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.)
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
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.
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]
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__')
>>> import inspect
>>>
>>> def foo():
... yield 'foo'
...
>>> print inspect.isgeneratorfunction(foo)
True
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 TypeError
s, 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.
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.