如何检查对象是否是Python中的迭代器?

问题描述:

我可以检查next()方法,但这足够吗?有没有意识形态的方法?如何检查对象是否是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,它存在严格允许与isinstanceissubclass)这样的检查。 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)是专门检查该情况的完全类似方法。

+9

这些问题询问对象是否是迭代器,而不是如果它是可迭代的。所以你应该使用collections.Iterator而不是collections.Iterable – 2010-06-11 17:04:40

+0

@Dave,对,让我编辑澄清。 – 2010-06-11 18:04:33

如果对象实现迭代器协议,则该对象是可迭代的。
你可以检查__iter__()方法存在有:

hasattr(object,'__iter__') 

在Python 2.x的这种方法忽略海峡对象和其他内置序列类型,如统一,x范围,缓冲区。它的工作原理在Python 3

另一种方式是与国际热核实验堆的方法来测试它:

try: 
    iter(object) 
except TypeError: 
    #not iterable 
+1

创建迭代器可能是昂贵的,而检查属性的存在总是*快*。 – 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 
+0

会调用'obj .__ iter __()'冒着改变某些东西的风险吗? – 2017-09-25 18:38:42

+0

@ BobStein-VisiBone:只有当对象有问题时。 – 2018-02-06 16:49:34