Как проверить, является ли объект объектом-генератором в python? - PullRequest
126 голосов
/ 20 июня 2011

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

Попытка -

>>> type(myobject, generator)

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

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

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

Ответы [ 7 ]

186 голосов
/ 20 июня 2011

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

>>> import types
>>> types.GeneratorType
<class 'generator'>
>>> gen = (i for i in range(10))
>>> isinstance(gen, types.GeneratorType)
True
32 голосов
/ 20 июня 2011

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

РЕДАКТИРОВАТЬ:

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

16 голосов
/ 03 сентября 2015

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

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

11 голосов
/ 18 мая 2012

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

def isgenerator(iterable):
    return hasattr(iterable,'__iter__') and not hasattr(iterable,'__len__')
2 голосов
/ 21 июня 2011
>>> import inspect
>>> 
>>> def foo():
...   yield 'foo'
... 
>>> print inspect.isgeneratorfunction(foo)
True
2 голосов
/ 21 июня 2011

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

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

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

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

1 голос
/ 14 сентября 2016

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

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]

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...