如何在Python中检查一个对象是否是生成器对象?

问题描述 投票:0回答:10

在Python中,如何检查一个对象是否是生成器对象?

尝试

>>> type(myobject, generator)

给出错误

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

(我知道我可以检查该对象是否有

__next__
方法使其成为生成器,但我想要某种方法来确定任何对象的类型,而不仅仅是生成器。)

python generator
10个回答
305
投票

您可以使用GeneratorType

中的
types
:

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

49
投票

你的意思是生成器函数?使用

inspect.isgeneratorfunction

编辑:

如果你想要一个生成器对象,你可以使用 inspect.isgenerator 正如 JAB 在他的评论中指出的那样。


42
投票

我认为区分 生成器函数生成器(生成器函数的结果)很重要:

>>> 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 中,有没有一种方法可以在调用函数之前检查它是否是“生成器函数”?


17
投票

如果您想检查纯生成器(即“生成器”类的对象),则

inspect.isgenerator
函数很好。但是,如果您检查例如
False
迭代,它将返回
izip
。检查广义生成器的另一种方法是使用此函数:

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

9
投票

您可以使用迭代器,或更具体地说,使用typing模块中的生成器。

from typing import Generator, Iterator
g = (i for i in range(1_000_000))
print(type(g))
print(isinstance(g, Generator))
print(isinstance(g, Iterator))

结果:

<class 'generator'>
True
True

7
投票

(我知道这是一篇旧帖子。)无需导入模块,您可以在程序开头声明一个对象进行比较:

gentyp= type(1 for i in "")                                                                                          
       ...
type(myobject) == gentyp

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

2
投票

如果您使用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]

如果您希望使用生成器作为线程替代方案或类似方法,这可能就是您想要的。


1
投票

我知道我可以检查该对象是否有下一个方法使其成为生成器,但我想要某种方法来确定任何对象的类型,而不仅仅是生成器。

不要这样做。这简直是一个非常非常糟糕的主意。

相反,请执行以下操作:

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

万一 for 循环体也有

TypeError
,有几种选择:(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) 修复应用程序的其他部分以适当地提供生成器。这通常比所有这些都简单。


0
投票

这是一个有点老的问题,但是我一直在为自己寻找类似的解决方案,但是对于异步生成器类,所以您可能会发现这很有帮助。

基于utdemir回复:

import types
isinstance(async_generator(), types.AsyncGeneratorType)
© www.soinside.com 2019 - 2024. All rights reserved.