迭代器(iterator)、可迭代对象(iterable)和迭代(iteration)是什么?

563
在Python中,“iterable”、“iterator”和“iteration”是什么意思?它们是如何定义的?
参见:如何构建基本迭代器?

希望能对你有所帮助:https://towardsdatascience.com/python-iterables-vs-iterators-688907fd755f - Giorgos Myrianthous
16个回答

3
iterable = [1, 2] 

iterator = iter(iterable)

print(iterator.__next__())   

print(iterator.__next__())   

所以,
  1. iterable 是一个可以被循环遍历的对象。例如:list,string,tuple等。

  2. 在我们的iterable对象上使用iter函数将返回一个迭代器对象

  3. 现在这个迭代器对象有一个名为__next__(在Python 3中,或者在Python 2中只是next)的方法,通过它可以访问可迭代对象的每个元素

所以,
输出以上代码将会是:

1

2


3
  • 可迭代对象(iterable)是指具有iter()方法并返回迭代器(iterator)的对象,它能够进行循环迭代操作。 例如:列表(list)是可迭代对象,因为可以对其进行循环迭代,但是列表并不是迭代器。
  • 迭代器(iterator)是指可以从中获取迭代器的对象,它是一个带有状态的对象,因此在迭代过程中记住了当前位置。

要查看对象是否具有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 方法来获取迭代器中的每个元素。


2
在处理可迭代对象和迭代器之前,决定可迭代对象和迭代器的主要因素是序列。
序列:序列是数据的集合。
可迭代对象:可迭代对象是支持__iter__方法的序列类型对象。
迭代方法:迭代方法将序列作为输入,并创建一个称为迭代器的对象。
迭代器:迭代器是调用next方法并遍历序列的对象。在调用next方法时,它返回当前遍历的对象。
例如:
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

1
只是一个观察:y=iter(x)并不完全等同于y=[1,2,3,4],因为y现在是一个迭代器对象。也许你应该添加一条注释来澄清它不是一个列表而是一个迭代器对象,或者改变表示方式。 - coelhudo

2
这是另一种使用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))))):

0
对我来说,Python的glossary对这些问题非常有帮助,例如对于可迭代对象,它的解释如下:
一个能够逐个返回其成员的对象。可迭代对象的示例包括所有序列类型(如列表、字符串和元组)以及一些非序列类型,如字典、文件对象和您使用iter()方法或实现了序列语义的getitem()方法定义的任何类的对象。
可迭代对象可以在for循环和许多其他需要序列的地方使用(如zip()、map()等)。当将可迭代对象作为参数传递给内置函数iter()时,它会返回该对象的迭代器。这个迭代器只能用于一次遍历值的集合。在使用可迭代对象时,通常不需要调用iter()或自己处理迭代器对象。for语句会自动为您执行这些操作,在循环期间创建一个临时的无名变量来保存迭代器。另请参见迭代器、序列和生成器。

0

其他人已经详细解释了什么是可迭代对象迭代器,所以我将尝试用同样的方式来解释生成器

在我看来,理解生成器的主要问题是“生成器”这个词的使用令人困惑,因为这个词有两个不同的含义:

  1. 作为创建(生成)迭代器工具
    • 函数返回迭代器的形式(即在其主体中使用yield语句),
    • 生成器表达式的形式
  2. 作为使用该工具的结果,即生成的迭代器。
    (在这个意义上,生成器迭代器的一种特殊形式——“生成器”这个词指出了这个迭代器是如何创建的。

生成器作为第一类工具:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接