Python似乎有两种方法来测试一个对象是否是一个生成器:
import types
isinstance(foo, types.GeneratorType)
或:
import inspect
inspect.isgenerator(foo)
本着“应该有一个 - 最好只有一个 - 显然是这样做的方式”的精神,这是另一种推荐的方式之一(大概是他们做同样的事情......如果没有,请赐教!)?
答案 0 :(得分:7)
它们是100%等价的:
>>> print(inspect.getsource(inspect.isgenerator))
def isgenerator(object):
"""Return true if the object is a generator.
Generator objects provide these attributes:
__iter__ defined to support interation over container
close raises a new GeneratorExit exception inside the
generator to terminate the iteration
gi_code code object
gi_frame frame object or possibly None once the generator has
been exhausted
gi_running set to 1 when generator is executing, 0 otherwise
next return the next item from the container
send resumes the generator and "sends" a value that becomes
the result of the current yield-expression
throw used to raise an exception inside the generator"""
return isinstance(object, types.GeneratorType)
我会说使用isinstance(object, types.GeneratorType)
应该是首选方式,因为它更清晰,更简单。
另外inspect.isgenerator
仅在python2.6中添加,这意味着使用isinstance
更向后兼容。
他们可能为对称性isgeneratorfunction
添加了isgenerator
函数,它做了不同的事情。
答案 1 :(得分:2)
您可以进行类型检查,但您可能不想检查只是生成器。你真正想要的是检查'迭代器',或者更确切地说,你需要两个迭代器。
import collections, itertools
def cheap_tee(foo):
if isinstance(foo, collections.Iterator):
# this is already an iterator, we need to 'tee' it
return itertools.tee(foo)
elif isinstance(foo, collections.Iterable):
# this is already an iterable, get two iterators from it:
return iter(foo), iter(foo)
raise TypeError("Don't know how to cheaply copy these", foo)
这将适用于远程可迭代的任何,而不仅仅是生成器表达式。某些类型将提供自定义迭代器,这些迭代器处理数据结构,这些数据结构不容易用生成器表达式或生成器表示,或者实现为C中的迭代器。要么也可以提供__copy__
itertools.tee
机制tee
实际使用也不会打扰重复工作。只有当它'真的已经是{{1}}无法为你复制的迭代器时,它才会使用空间,为你做所有的结晶。
答案 2 :(得分:1)
你应该能够做到:
try:
x = possible_generator.next()
mylist = [x] + list(possible_generator)
except:
pass
这将区分生成器和内置迭代器;但是,如果你有一个类似于列表但下一步实现的自定义类,那么它将会失败。