3分钟理清可迭代、迭代器、生成器的概念,掌握Python3中迭代器的使用方法

迭代器Iterator的特点

举个生动例子:给马场里所有马洗澡,确保每一匹马都被洗到且只洗一次。

马群分别通过ListIterator两种形式,加载到for循环中执行,我们对比看一下有什么不同。

List

  • 所有的马抓到澡堂子里关起来;(先算出所有的要循环的元素,一起加载到内存)
  • 然后挨个洗澡;(顺序执行)
  • 都洗完了一起放出来。(执行期间所有元素都占着内存)

Iterator

  • 先不用管马场里有多少马,确认马场只出不进;(定义迭代器对象)
  • 每次抓一匹马出来洗澡然后放走;(next()取出一个元素执行,每次都是用到的时候才去计算一个元素来,所以相比list几乎不占内存)
  • 直到没马可抓。(直到执行完毕)

迭代器的省内存、局部效率高的特点一目了然。

另外迭代器只能遍历一次。
for i in List 执行完毕后可以马上重复使用for i in List再来一遍。而迭代器的for循环本质上还是next(),因此在for i in Iterator 执行完毕后,Iterator中已经没有元素可输出,需要重新定义迭代器,才能再执行for i in Iterator 输出元素。

可迭代、迭代器、生成器区别

生成器是迭代器中的一种。
写成数学表达的形式,大概可以理解为:

可迭代Iterable

所有可以用for循环的对象。
比如listtupledictsetstrIteratorgenerator

>>> for i in 'ab':
        print(i)
a
b

迭代器Iterator

可以被next()函数调用并不断返回下一个值的对象。
比如iter(list)iter(tuple)iter(dict)iter(set)iter(str)generator

>>> x = iter('ab')
>>> print(x)
<str_iterator object at 0x00000000025BA860>
>>> next(x)
a

注意:当next()执行到直到没有数据时,会抛出StopIteration错误。
只不过通常我们都是通过for循环来迭代它,并不需要关心StopIteration的错误。

>>> for i in iter('ab'):
        print(i)
a
b

生成器generator

同样可以被next()函数调用并不断返回下一个值的对象。其实还是迭代器。
只不过是生成器是通过yield方法生成器表达式产生的。

# 方法一:yield方法。如果一个函数定义中包含yield,那么这个函数就由普通函数变成了生成器。
>>> def geti():
>>>     for i in 'ab':
>>>         yield i
>>> x = geti()
>>> print(x)
<generator object geti at 0x0000000003C08728>
# 方法二:生成器表达式。其实就是列表生成式的[]改成(),就创建了一个生成器。
>>> y = (i for i in 'ab')
>>> print(y)
<generator object <genexpr> at 0x0000000003C49200>

需要注意的是:遇到yield回传,下次执行,是从之前回传断开的地方继续执行。
下面例子中可以看到:第二次使用next的时候,是先执行完了yield后面的语句,才进入到下一个for循环的。

>>> def geti():
>>>     for i in 'ab':
>>>         yield i
>>>         print('is',i)
>>> x = geti()
>>> print(next(x))
a
>>> print(next(x))
is a
b
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章