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

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

Попытка -

>>> type(myobject, generator)

дает ошибку -

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

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

94
задан Pushpak Dagade 20 июня '11 в 22:42
источник поделиться
7 ответов

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

>>> import types
>>> types.GeneratorType
<class 'generator'>
>>> gen = (i for i in range(10))
>>> isinstance(gen, types.GeneratorType)
True
133
ответ дан utdemir 20 июня '11 в 22:46
источник поделиться

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

EDIT:

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

22
ответ дан mouad 20 июня '11 в 22:44
источник поделиться

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

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

10
ответ дан Robert Lujo 03 сент. '15 в 19:17
источник поделиться

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

def isgenerator(iterable):
    return hasattr(iterable,'__iter__') and not hasattr(iterable,'__len__')
9
ответ дан Luca Sbardella 18 мая '12 в 0:52
источник поделиться

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

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

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

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

2
ответ дан S.Lott 20 июня '11 в 23:04
источник поделиться
>>> import inspect
>>> 
>>> def foo():
...   yield 'foo'
... 
>>> print inspect.isgeneratorfunction(foo)
True
2
ответ дан Corey Goldberg 20 июня '11 в 23:14
источник поделиться

Если вы используете веб-сервер 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]

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

1
ответ дан user6830669 14 сент. '16 в 14:31
источник поделиться

Другие вопросы по меткам или Задайте вопрос