如何检查对象是否是Python中的迭代器?
在Python 2.6或更高,所设计的,在成语对于这种行为的检查是一种“成员资格检查”与抽象基类的collections
模块的标准库中:
>>> import collections
>>> isinstance('ciao', collections.Iterable)
True
>>> isinstance(23, collections.Iterable)
False
>>> isinstance(xrange(23), collections.Iterable)
True
事实上,这种检查是首要的设计原因,新的抽象基类(第二重要的是在一些提供“混入功能”案件,这就是为什么他们是ABC rath呃不只是接口 - 但这不适用于collections.Iterable
,它存在严格允许与isinstance
或issubclass
)这样的检查。 ABCs允许那些实际上并不从它们继承的类被“注册”为子类,因此这些类可以是ABC的“子类”,用于这种检查;并且他们可以在内部执行特殊方法所需的全部检查(本例中为__iter__
),因此您不必这样做。
如果你坚持与Python的旧版本,“这是更好地请求原谅比许可”:
def isiterable(x):
try: iter(x)
except TypeError: return False
else: return True
但是这没有那么快,简洁的新方法。
请注意,对于这种特殊情况,您经常需要特殊字符串(这是可迭代的,但大多数应用程序上下文无论如何都要将其视为“标量”)。不管你的方法是使用检查iterableness,如果你需要这种特殊的外壳只是在前面加上一个检查isinstance(x, basestring)
- 例如:
def reallyiterable(x):
return not isinstance(x, basestring) and isinstance(x, collections.Iterable)
编辑:如在评论中指出,问题集中在是否一个对象是一个****,而不是它是否可以***(所有迭代器都可迭代,但反之亦然 - 并非所有迭代器都是迭代器)。 isinstance(x, collections.Iterator)
是专门检查该情况的完全类似方法。
如果对象实现迭代器协议,则该对象是可迭代的。
你可以检查__iter__()
方法存在有:
hasattr(object,'__iter__')
在Python 2.x的这种方法忽略海峡对象和其他内置序列类型,如统一,x范围,缓冲区。它的工作原理在Python 3
另一种方式是与国际热核实验堆的方法来测试它:
try:
iter(object)
except TypeError:
#not iterable
创建迭代器可能是昂贵的,而检查属性的存在总是*快*。 – 2012-09-29 16:35:58
要成为一个迭代的对象必须通过三个测试:
-
obj
具有(在Python 3或__next__
)的__iter__
方法 -
obj
具有next
方法 -
obj.__iter__()
返回obj
所以,一个自己的测试会看起来像:
def is_iterator(obj):
if (
hasattr(obj, '__iter__') and
hasattr(obj, 'next') and # or __next__ in Python 3
callable(obj.__iter__) and
obj.__iter__() is obj
):
return True
else:
return False
会调用'obj .__ iter __()'冒着改变某些东西的风险吗? – 2017-09-25 18:38:42
@ BobStein-VisiBone:只有当对象有问题时。 – 2018-02-06 16:49:34
这些问题询问对象是否是迭代器,而不是如果它是可迭代的。所以你应该使用collections.Iterator而不是collections.Iterable – 2010-06-11 17:04:40
@Dave,对,让我编辑澄清。 – 2010-06-11 18:04:33