我可以查看next()
方法,但这还够吗?有没有一种思想方式?
答案 0 :(得分:52)
在Python 2.6或更高版本中,这种行为检查的设计用语是对标准库的collections
模块中的抽象基类进行“成员资格检查”:
>>> import collections
>>> isinstance('ciao', collections.Iterable)
True
>>> isinstance(23, collections.Iterable)
False
>>> isinstance(xrange(23), collections.Iterable)
True
实际上,这种检查是新抽象基类的主要设计原因(第二个重要的是在某些情况下提供“mixin功能”,这就是为什么它们是ABCs而不仅仅是接口 - 但是这不适用于collections.Iterable
,严格以允许使用isinstance
或issubclass
进行此类检查。 ABCs允许实际上不从它们继承的类被“注册”为子类,因此这些类可以是ABC的“子类”以进行此类检查;并且,他们可以在内部执行特殊方法的所有必要检查(在这种情况下为__iter__
),因此您不必这样做。
如果您遇到旧版本的Python,“最好是请求宽恕而非许可”:
def isiterable(x):
try: iter(x)
except TypeError: return False
else: return True
但这并不像新方法那么快速和简洁。
请注意,对于这种特殊情况,您通常需要特殊情况字符串(可迭代但大多数应用程序上下文无论如何都要视为“标量”)。无论您使用什么方法来检查可迭代性,如果您需要这样的特殊套管,只需要检查isinstance(x, basestring)
- 例如:
def reallyiterable(x):
return not isinstance(x, basestring) and isinstance(x, collections.Iterable)
编辑:正如评论中指出的那样,问题集中在一个物体是否是一个物品***而不是它是否真的*** *** ***迭代器是可迭代的,但反之亦然 - 并非所有迭代都是迭代器)。 isinstance(x, collections.Iterator)
是完全类似的方式来检查这种情况。
答案 1 :(得分:15)
如果对象实现了迭代器协议,则该对象是可迭代的
您可以使用以下方法检查__iter__()
方法是否存在
hasattr(object,'__iter__')
在Python 2.x中,这种方法错过了str对象和其他内置序列类型,如unicode,xrange,buffer。它适用于Python 3。
另一种方法是用iter方法测试它:
try:
iter(object)
except TypeError:
#not iterable
答案 2 :(得分:6)
要成为迭代器,对象必须通过三次测试:
obj
有一个__iter__
方法obj
有next
方法(或Python 3中的__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
答案 3 :(得分:0)
来自python源代码文档注释的答案:
{python安装路径} /Versions/3.5/lib/python3.5/types.py
# Iterators in Python aren't a matter of type but of protocol. A large
# and changing number of builtin types implement *some* flavor of
# iterator. Don't check the type! Use hasattr to check for both
# "__iter__" and "__next__" attributes instead.
答案 4 :(得分:0)
由于问题是关于迭代器不可迭代,并考虑使用迭代器,这是一种最简单,最Python化的方法
iterable = [1,2]
iterator = iter(iterable)
def isIterator(obj):
try:
next(obj, None)
return True
except TypeError:
return False
>>> isIterator(iterable)
False
>>> isIterator(iterator)
True
是的。检查next()应该足够
答案 5 :(得分:0)
有比其他答案建议的更好的方法。
在Python中,我们有两种东西:Iterable
和Iterator
。如果对象可以给您Iterable
,则它是Iterator
。当您在其上使用iter()
时,它会这样做。如果可以使用Iterator
顺序浏览其元素,则该对象为next()
。例如,map()
返回Iterator
,而list
是Iterable
。
这里是more details。
下面的代码说明了如何检查这些类型:
from collections.abc import Iterable, Iterator
r = [1, 2, 3]
e = map(lambda x:x, r)
print(isinstance(r, Iterator)) # False, because can't apply next
print(isinstance(e, Iterator)) # True
print(isinstance(r, Iterable)) # True, because can apply iter()
print(isinstance(e, Iterable)) # True, note iter() returns self
答案 6 :(得分:0)
此示例来自 Effective Python 一书,并在此post中进行了说明。
一个Iterable产生一个迭代器。任何迭代器也是可迭代的 但将其自身作为迭代器:
>>> list_iter = iter([]) >>> iter(list_iter) is list_iter True
答案 7 :(得分:0)
from collections.abc import Iterator
isinstance(object, Iterator)