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

如何在python中检查对象是否是生成器对象?,python,generator,Python,Generator,在python中,如何检查对象是否是生成器对象 试一试- >>> type(myobject, generator) 给出了错误- Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'generator' is not defined 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 NameError:未定义名称“生成

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

试一试-

>>> type(myobject, generator)
给出了错误-

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'generator' is not defined
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
NameError:未定义名称“生成器”

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

你是指生成器功能吗?使用

编辑:


如果您想要一个generator对象,您可以使用JAB在其评论中指出的方法。

您可以使用GeneratorType from types:

>>> import types
>>> types.GeneratorType
<class 'generator'>
>>> gen = (i for i in range(10))
>>> isinstance(gen, types.GeneratorType)
True
导入类型 >>>类型。生成器类型 >>>gen=(范围(10)内的i代表i) >>>isinstance(gen,types.GeneratorType) 真的 我知道我可以检查对象是否有下一个方法,使其成为生成器,但我想使用某种方法来确定任何对象的类型,而不仅仅是生成器

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

相反,请执行以下操作:

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
s,则有几种选择:(1)定义函数以限制错误的范围,或(2)使用嵌套的try

或者(3)类似的东西来区分所有这些浮动的
TypeError
s

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)修复应用程序的其他部分以适当地提供生成器。这通常比所有这一切都要简单。

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

>>> import inspect
>>> 
>>> def foo():
...   yield 'foo'
... 
>>> print inspect.isgeneratorfunction(foo)
True
def isgenerator(iterable):
    return hasattr(iterable,'__iter__') and not hasattr(iterable,'__len__')

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

调用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]

另请参见

如果您使用的是tornado webserver或类似工具,您可能会发现服务器方法实际上是生成器,而不是方法。这使得调用其他方法变得困难,因为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]

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

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

结果:

真的
真的
(我知道这是一篇老文章。)无需导入模块,您可以在程序开始时声明一个对象进行比较:

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


你想解决什么实际问题?发布更多上下文,可能有一种更聪明的方法。为什么需要知道它是否是生成器?
从类型导入生成器类型;类型(myobject,GeneratorType)
将为“generator”类的对象提供正确的结果。但正如Daenyth所暗示的,这并不一定是正确的方法。如果你在检查
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,由于希望多次迭代同一集合。对于想了解用例的人来说,当您需要知道迭代器是否将被使用时,这可能很有用(例如,如果您的函数接受任何迭代器,但需要多次迭代,则您希望在迭代之前将其具体化)生成器函数不是生成器对象;见@utdemir'sanswer@Piotr:在这种情况下,您可以使用@JAB,@Piotr:Reflected来解决OP可能意味着什么的所有可能性,谢谢JAB:)注意:如果您只需要此测试,您可以通过使用来避免一点开销,因为
inspect.isgenerator
只是:。的简写形式。有关generator对象和generator函数之间的区别,请参阅@RobertLujo answer。您的解决方案将捕获for循环体抛出的类型错误。我已经提出了一个可以防止这种不良行为的编辑方法。如果我没有弄错的话,这是一种更具python风格的方法。尽管如此,如果你在一个项目列表上进行迭代,并且更多的项目不是迭代器而不是迭代器,那么这肯定需要更长的时间?@Jakob Bowyer:异常比
if
语句更快。和。这种微观优化是浪费时间。修正生成迭代器和非迭代器混合包的算法,只生成迭代器,省去所有这些麻烦。这会错误地将任何iterable假设为生成器。这只有在它是函数时才有效。如果“foo”是生成器对象,则显示“False”。请看我的问题,我想检查生成器对象。嗯。对于
x=iter([1,2])
,返回true。在我看来,它实际上是在测试对象是否是迭代器,而不是生成器。但也许“迭代器”正是您所说的“通用生成器”的意思。我最喜欢的解决方案,尽管应该注意,它不将
range
计算为生成器(技术上正确),但对我来说很烦人,因为
range
具有不同类型的py2和3dict。values()是生成器,但是有“\uuu len\uuuuu”很遗憾,这不适用于生成器类(例如,map或filter对象)。可能
isinstance(gen,(types.GeneratorType,map,filter))
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
gentyp= type(1 for i in "")                                                                                          
       ...
type(myobject) == gentyp