Как проверить, является ли объект объектом-генератором в python?

В python, как проверить, является ли объект объектом генератора?

Попытка -

>>> type(myobject, generator)

дает ошибку -

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

(Я знаю, что могу проверить, имеет ли объект метод next для него как генератор, но я хочу каким-то образом использовать, чтобы определить тип любого объекта, а не только генераторы.)

Ответ 1

Вы можете использовать GeneratorType из типов:

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

Ответ 2

Вы имеете в виду функции генератора? используйте inspect.isgeneratorfunction.

EDIT:

если вы хотите создать объект-генератор, вы можете использовать inspect.isgenerator, как указано JAB в его комментарии.

Ответ 3

Я думаю, что важно проводить различие между функциями генератора и генераторами (результат функции генератора):

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

Вызов generator_function не даст нормального результата, он даже не выполнит никакого кода в самой функции, результатом будет специальный объект, называемый generator:

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

так что это не функция генератора, а генератор:

>>> inspect.isgeneratorfunction(generator)
False

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

и функция генератора не является генератором:

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

просто для справки, фактический вызов тела функции будет происходить при использовании генератора, например:

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

Смотрите также В Python есть ли способ проверить, является ли функция "генератором", прежде чем вызывать ее?

Ответ 4

Функция inspect.isgenerator прекрасна, если вы хотите проверить чистые генераторы (т.е. объекты класса "генератор" ). Однако он вернет False, если вы проверите, например, izip итерабельность. Альтернативным способом проверки генератора является использование этой функции:

def isgenerator(iterable):
    return hasattr(iterable,'__iter__') and not hasattr(iterable,'__len__')

Ответ 5

Я знаю, что могу проверить, есть ли у объекта следующий метод, чтобы он был генератором, но я хочу каким-то образом использовать, что я могу определить тип любого объекта, а не только генераторы.

Не делай этого. Это просто очень и очень плохая идея.

Вместо этого сделайте следующее:

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

В маловероятном случае, когда тело цикла для также имеет TypeError s, существует несколько вариантов: (1) определить функцию для ограничения объема ошибок или (2 ) используйте вложенный блок try.

Или (3) что-то подобное, чтобы различать все эти TypeError, которые плавают вокруг.

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`

Или (4) исправить другие части вашего приложения, чтобы обеспечить генераторы соответствующим образом. Это часто проще, чем все это.

Ответ 6

>>> import inspect
>>> 
>>> def foo():
...   yield 'foo'
... 
>>> print inspect.isgeneratorfunction(foo)
True

Ответ 7

Если вы используете веб-сервер tornado или аналогичный, вы могли бы обнаружить, что серверные методы на самом деле являются генераторами, а не методами. Это затрудняет вызов других методов, потому что выход не работает внутри метода, и поэтому вам нужно начать управлять пулами связанных объектов-генераторов. Простым методом управления пулами цепных генераторов является создание вспомогательной функции, например

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

Теперь записываем цепочечные генераторы, такие как

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

Производит вывод

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

Скорее всего, это то, что вы хотите, если хотите использовать генераторы в качестве альтернативы потока или аналогичного.

Ответ 8

Этот тест, кажется, работает, по крайней мере, для примера, который я попробовал:

str(type(object))=="<class 'generator'>"