[英]How can I check if an object is an iterator in Python?
我可以检查next()
方法,但这是否足够? 有没有意识形态的方法?
在 Python 2.6 或更高版本中,此类行为检查的设计习惯用法是使用标准库collections
模块中的抽象基类进行“成员资格检查”:
>>> import collections
>>> isinstance('ciao', collections.Iterable)
True
>>> isinstance(23, collections.Iterable)
False
>>> isinstance(xrange(23), collections.Iterable)
True
事实上,这种检查是新抽象基类的主要设计原因(第二个重要的原因是在某些情况下提供“混合功能”,这就是为什么它们是 ABC 而不仅仅是接口——但这不是t 适用于collections.Iterable
,它严格存在以允许使用isinstance
或issubclass
进行此类检查)。 ABC 允许实际上并不从它们继承的类无论如何“注册”为子类,以便此类类可以是 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)
是专门检查该条件的完全类似的方法。
如果一个对象实现了迭代器协议,那么它就是可迭代的。
您可以使用以下方法检查__iter__()
方法的存在:
hasattr(object,'__iter__')
在 Python 2.x 中,这种方法会遗漏 str 对象和其他内置序列类型,如 unicode、xrange、buffer。 它适用于 Python 3。
另一种方法是使用 iter 方法对其进行测试:
try:
iter(object)
except TypeError:
#not iterable
要成为迭代器,对象必须通过三个测试:
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
有比其他答案所建议的更好的方法。
在 Python 中,我们有两种东西: Iterable
和Iterator
。 如果一个对象可以给你Iterator
它就是Iterable
。 当您在其上使用iter()
时它iter()
。 如果您可以使用next()
顺序浏览其元素,则该对象是Iterator
。 例如, map()
返回Iterator
并且list
是Iterable
。
这里有更多细节。
下面的代码说明了如何检查这些类型:
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
来自 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.
from collections.abc import Iterator
isinstance(object, Iterator)
如果您想检查该值是否可迭代,您可以执行以下操作:
>>> from typing import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance(1, Iterable)
False
如果您想检查它是否是迭代器,您可以执行以下操作:
>>> hasattr(obj, "__iter__") and hasattr(obj, "__next__")
True
这个例子来自《 Effective Python 》一书,并在这篇文章中进行了说明。
一个迭代器产生一个迭代器。 任何迭代器也是可迭代的,但将自身生成为迭代器:
>>> list_iter = iter([]) >>> iter(list_iter) is list_iter True
if '__iter__' in dir(object):
#code
else:
#code
由于问题是关于 Iterator not Iterable 并考虑使用 iterator,这是一种最简单的 Pythonic 方法
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() 应该就足够了
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.