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

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

попытке это -

>>> type(myobject, generator)

выдает ошибку -

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

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

7 ответов


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

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

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

EDIT:

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


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

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

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

>>> 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 есть ли способ проверить, является ли функция "функцией генератора" перед ее вызовом?


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

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

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

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

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

вместо этого:

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

в маловероятном случае, если тело на loop также имеет TypeErrors, есть несколько вариантов: (1) Определите функцию, чтобы ограничить область действия ошибки или (2) Использование вложенного попробовать блок.

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

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) исправьте другие части вашего приложения, чтобы обеспечить генераторы соответствующим образом. Это часто проще, чем все это.


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

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

Теперь пишем цепные генераторы такие as

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

выдает

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

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