在Python中,“iterable”、“iterator”和“iteration”是什么意思?它们是如何定义的?
参见:如何构建基本迭代器?
参见:如何构建基本迭代器?
iterable = [1, 2]
iterator = iter(iterable)
print(iterator.__next__())
print(iterator.__next__())
iterable
是一个可以被循环遍历的对象。例如:list,string,tuple等。
在我们的iterable
对象上使用iter
函数将返回一个迭代器对象。
现在这个迭代器对象有一个名为__next__
(在Python 3中,或者在Python 2中只是next
)的方法,通过它可以访问可迭代对象的每个元素。
1
2
要查看对象是否具有iter()方法,我们可以使用以下函数。
ls = ['hello','bye']
print(dir(ls))
输出
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
正如你所见,iter() 表示它是一个可迭代对象,但不包含 iterator 对象的特征,即没有包含 next() 方法。
在 Python 中,无论是使用 for 循环、map 还是列表推导式,都会自动调用 next 方法来获取迭代器中的每个元素。
__iter__
方法的序列类型对象。x=[1,2,3,4]
x是一个由数据集合组成的序列
y=iter(x)
调用iter(x)
时,只有当x对象具有迭代器方法时,它才返回迭代器,否则会引发异常。如果它返回迭代器,则将y分配如下:
y=[1,2,3,4]
由于y是迭代器,因此它支持next()
方法。
调用next方法时,它会逐个返回列表中的元素。
在返回序列的最后一个元素后,如果再次调用next方法,则会引发StopIteration错误。
示例:
>>> y.next()
1
>>> y.next()
2
>>> y.next()
3
>>> y.next()
4
>>> y.next()
StopIteration
collections.abc
的视图。这个视图可能在第二次或以后有用。collections.abc
中,我们可以看到以下层次结构:builtins.object
Iterable
Iterator
Generator
即生成器是从迭代器派生而来,迭代器又是从可迭代对象派生而来,可迭代对象最终是从基本对象派生而来。
因此,
每个迭代器都是可迭代的,但不是每个可迭代的对象都是迭代器。例如,[1, 2, 3]
和range(10)
是可迭代的,但不是迭代器。x = iter([1, 2, 3])
是一个迭代器,也是一个可迭代的对象。iter()
会返回它本身。因此,如果it
是一个迭代器,则iter(it) is it
为True。[2 * x for x in nums]
这样的列表推导式或像for x in nums:
这样的循环语句,就好像在可迭代对象(nums
)上调用了iter()
,然后使用该迭代器迭代nums
。因此,以下所有内容在功能上都是等效的(例如,nums=[1, 2, 3]
):
for x in nums:
for x in iter(nums):
for x in iter(iter(nums))
:for x in iter(iter(iter(iter(iter(nums))))):
其他人已经详细解释了什么是可迭代对象和迭代器,所以我将尝试用同样的方式来解释生成器。
在我看来,理解生成器的主要问题是“生成器”这个词的使用令人困惑,因为这个词有两个不同的含义:
yield
语句),生成器作为第一类工具:
In[2]: def my_generator():
...: yield 100
...: yield 200
In[3]: my_generator
Out[3]: <function __main__.my_generator()>
In[4]: type(my_generator)
Out[4]: function
使用此工具的结果是生成器(即迭代器):
In[5]: my_iterator = my_generator()
In[6]: my_iterator
Out[6]: <generator object my_generator at 0x00000000053EAE48>
In[7]: type(my_iterator)
Out[7]: generator
生成器是第二类工具,与该工具的结果迭代器无法区分:
In[8]: my_gen_expression = (2 * i for i in (10, 20))
In[9]: my_gen_expression
Out[9]: <generator object <genexpr> at 0x000000000542C048>
In[10]: type(my_gen_expression)
Out[10]: generator