在 Python 中似乎有两种方法可以测试一个对象是否是生成器:
import types
isinstance(foo, types.GeneratorType)
或者:
import inspect
inspect.isgenerator(foo)
本着“应该有一种——最好只有一种——明显的方式来做到这一点。”的精神,是推荐的这些方式之一(大概他们做同样的事情......如果没有,请赐教!)?
在 Python 中似乎有两种方法可以测试一个对象是否是生成器:
import types
isinstance(foo, types.GeneratorType)
或者:
import inspect
inspect.isgenerator(foo)
本着“应该有一种——最好只有一种——明显的方式来做到这一点。”的精神,是推荐的这些方式之一(大概他们做同样的事情......如果没有,请赐教!)?
它们是 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)
我会说 usingisinstance(object, types.GeneratorType)
应该是首选方式,因为它更清晰,更简单。也inspect.isgenerator
只在python2.6中添加,这意味着使用isinstance
更加向后兼容。
他们可能添加了isgenerator
对称功能,isgeneratorfunction
它做了一些不同的事情。
您可以进行类型检查,但您可能不想只检查生成器。你真正想要的是检查'迭代器',或者更确切地说,你想要两个迭代器。
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
不能为你复制的迭代器时,它才会使用空间,为你完成所有的结晶。
你应该能够做到:
try:
x = possible_generator.next()
mylist = [x] + list(possible_generator)
except:
pass
这将区分生成器和内置迭代器;但是,如果您有一个类似于列表但也实现了 next 的自定义类,那么它将失败。