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

问题:如何检查对象是否是python中的生成器对象?

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

试试这个-

>>> type(myobject, generator)

给出错误-

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

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

In python, how do I check if an object is a generator object?

Trying this –

>>> type(myobject, generator)

gives the error –

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

(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.)


回答 0

您可以从以下类型使用GeneratorType:

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

You can use GeneratorType from types:

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

回答 1

你的意思是生成器功能?使用inspect.isgeneratorfunction

编辑:

如果需要生成器对象,可以使用JAB在其注释中指出的inspect.isgenerator

You mean generator functions ? use inspect.isgeneratorfunction.

EDIT :

if you want a generator object you can use inspect.isgenerator as pointed out by JAB in his comment.


回答 2

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

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

I think it is important to make distinction between generator functions and generators (generator function’s result):

>>> def generator_function():
...     yield 1
...     yield 2
...
>>> import inspect
>>> inspect.isgeneratorfunction(generator_function)
True

calling generator_function won’t yield normal result, it even won’t execute any code in the function itself, the result will be special object called generator:

>>> generator = generator_function()
>>> generator
<generator object generator_function at 0x10b3f2b90>

so it is not generator function, but generator:

>>> inspect.isgeneratorfunction(generator)
False

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

and generator function is not generator:

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

just for a reference, actual call of function body will happen by consuming generator, e.g.:

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

See also In python is there a way to check if a function is a “generator function” before calling it?


回答 3

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

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

The inspect.isgenerator function is fine if you want to check for pure generators (i.e. objects of class “generator”). However it will return False if you check, for example, a izip iterable. An alternative way for checking for a generalised generator is to use this function:

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

回答 4

您可以使用输入模块中的Iterator或更具体地说,使用Generator 。

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

You could use the Iterator or more specifically, the Generator from the typing module.

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))

result:

<class 'generator'>
True
True

回答 5

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

回答 6

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

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

相反,请执行以下操作:

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)像这样的东西来区分所有这些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)修复应用程序的其他部分,以适当地提供生成器。这通常比所有这些都简单。

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.

Don’t do this. It’s simply a very, very bad idea.

Instead, do this:

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

In the unlikely event that the body of the for loop also has TypeErrors, there are several choices: (1) define a function to limit the scope of the errors, or (2) use a nested try block.

Or (3) something like this to distinguish all of these TypeErrors which are floating around.

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`

Or (4) fix the other parts of your application to provide generators appropriately. That’s often simpler than all of this.


回答 7

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

如果您希望将生成器用作线程替代或类似线程,则可能是您想要的。

If you are using tornado webserver or similar you might have found that server methods are actually generators and not methods. This makes it difficult to call other methods because yield is not working inside the method and therefore you need to start managing pools of chained generator objects. A simple method to manage pools of chained generators is to create a help function such as

def chainPool(*arg):
    for f in arg:
      if(hasattr(f,"__iter__")):
          for e in f:
             yield e
      else:
         yield f

Now writing chained generators such as

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

Produces output

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

Which is probably what you want if your looking to use generators as a thread alternative or similar.


回答 8

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

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

(I know it’s an old post.) There is no need to import a module, you can declare an object for comparison at the beginning of the program:

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