如何检查对象是否是Python中的生成器对象?

How to check if an object is a generator object in python?

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

尝试这个

1
>>> type(myobject, generator)

给出了错误-

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

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


可以使用以下类型的GeneratorType:

1
2
3
4
5
6
>>> import types
>>> types.GeneratorType
<class 'generator'>
>>> gen = (i for i in range(10))
>>> isinstance(gen, types.GeneratorType)
True


你是说发电机的功能?使用inspect.isgeneratorfunction

编辑:

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


我认为区分发电机功能和发电机(发电机功能的结果)很重要:

1
2
3
4
5
6
7
>>> def generator_function():
...     yield 1
...     yield 2
...
>>> import inspect
>>> inspect.isgeneratorfunction(generator_function)
True

调用generator_函数不会产生正常结果,甚至不会在函数本身执行任何代码,结果将是名为generator的特殊对象:

1
2
3
>>> generator = generator_function()
>>> generator
<generator object generator_function at 0x10b3f2b90>

所以它不是发电机功能,而是发电机:

1
2
3
4
5
6
>>> inspect.isgeneratorfunction(generator)
False

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

发电机功能不是发电机:

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

仅作为参考,实际调用函数体时会使用生成器,例如:

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

另请参见在python中,是否有一种方法在调用函数之前检查函数是否是"生成器函数"?


如果要检查纯生成器(即"Generator"类的对象),则inspect.isgenerator函数可以。但是,如果您检查(例如)izip的iterable,它将返回False。检查通用发电机的另一种方法是使用此功能:

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


1
2
3
4
5
6
7
>>> import inspect
>>>
>>> def foo():
...   yield 'foo'
...
>>> print inspect.isgeneratorfunction(foo)
True


I know I can check if the object has a next method for it to be a generator, but I want some way using which I can determine the type of any object, not just generators.

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

相反,请执行以下操作:

1
2
3
4
5
6
7
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循环体也有TypeErrors的不太可能的情况下,有几种选择:(1)定义函数以限制错误的范围,或(2)使用嵌套的try块。

或者(3)像这样的东西来区分漂浮在周围的所有这些TypeErrors。

1
2
3
4
5
6
7
8
9
10
11
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 Web服务器或类似服务器,您可能会发现服务器方法实际上是生成器,而不是方法。这使得调用其他方法变得困难,因为yield在方法内部不起作用,因此需要开始管理链接生成器对象的池。管理链接生成器池的一个简单方法是创建一个帮助函数,例如

1
2
3
4
5
6
7
def chainPool(*arg):
    for f in arg:
      if(hasattr(f,"__iter__")):
          for e in f:
             yield e
      else:
         yield f

现在编写链生成器,如

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

产出产出

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

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