深入浅析Python中的迭代器


Posted in Python onJune 04, 2019

目录结构:

contents structure [-]

在开始文章之前,先贴上一张Iterable、Iterator与Generator之间的关系图:

深入浅析Python中的迭代器 

1. Iterator VS Iterable

迭代器(Iterator)

迭代器是实现了迭代器协议的类对象,迭代器协议规定了迭代器类必需定义__next()__方法。当对迭代器对象调用next()方法时,对象会去调用__next()__计算迭代器的返回值。

可迭代对象(Iterable)

可迭代对象可以是任何对象,不一定是能返回迭代器的数据结构。一个可迭代对象会直接或间接性的调用这两个方法__iter()__和__next()__;其中__iter()__方法只能返回迭代器对象,__next()__则供给迭代器进行调用。

通常情况下,可迭代类都会实现__iter()__和__next()__,并且__iter()__返回它自己,换句话说,该类即是迭代器又是可迭代类。

下面的代码展示了迭代器和可迭代器对象之间的差别:

a_set = {1, 2, 3}#定义set数据类型,set是可迭代类型
b_iterator = iter(a_set)#得到set的迭代器
#Output: 1
print(next(b_iterator))
#Output: <class 'set'>
print(type(a_set))
#Output: <class 'set_iterator'>
print(type(b_iterator))

从结果可以看出a_set是一个可迭代类型(set类型),b_iterator是一个迭代器(set_iterator),它们两个是完全不一同的类型。

下面的自定义了一个迭代器:

class Series(object):
 def __init__(self, low, high):
  self.current = low
  self.high = high
 def __iter__(self):
  return self
 def __next__(self):
  if self.current > self.high:
   raise StopIteration
  else:
   self.current += 1
   return self.current - 1
n_list = Series(1,10) 
print(list(n_list))

从上面的代码可以看出,__iter__返回了迭代器本身。__next__返回迭代器的下一个值,如果没有下一个返回值那么会抛出StopIteration异常。如果没有在合适的位置抛出StopIteration异常结束迭代,那么在某些循环语句中(例如:for loop),将会形成死循环,所以在__next__中必需要在合适位置添加退出语句(抛出StopIterator异常)。

2.Itertools 模块

Itertools是Python的内置模块,其中包含了能够创建迭代器的函数。简而言之,它提供了许多能够与迭代器交互的方法。

下面是我们使用Itertools模块中count函数的案例:

from itertools import count
sequence = count(start=0, step=1)
while(next(sequence) <= 10):
 print(next(sequence),end=" ")

输出:

Itertools中的cycle函数可以创建无限迭代器,例如:

from itertools import cycle
dessert = cycle(['Icecream','Cake'])
count = 0
while(count != 4):
 print('Q. What do we have for dessert? A: ' + next(dessert))
 count+=1

输出:

Q. What do we have for dessert? A: Icecream
Q. What do we have for dessert? A: Cake
Q. What do we have for dessert? A: Icecream
Q. What do we have for dessert? A: Cake

关于更多itertools模块的使用, 可以参见python文档 。

3.生成器(Generator)

生成器可以说是迭代器的亲兄弟,生成器允许我们像上面那样写迭代器而不用额外定义__iter__()和__next__()方法。

看下面的案例:

def series_generator(low, high):
 while low <= high:
  yield low
  low += 1
n_list = []
for num in series_generator(1,10):
 n_list.append(num)
print(n_list)

如果一个方法中出现了yield关键字,那么该方法就是一个生成器。生成器中没有return语句,函数的返回值实际上是一个generator。当循环开始执行到yield语句后,low的值会被扩展到要返回的generator中。当下一次循环到达yield语句时,generator会从上一次停止的地方恢复执行,并且将最新的low值添加到generator中。循环一直运行下去,直到low>high退出循环。

生成器支持延迟计算,只有当去取生成器中的值时才会计算。

例如:

def test():
 print("进入test函数")
 for i in range(2):
  print("yield number ",i)
  yield i
if "__main__" == __name__:
 print("开始调用test")
 res = test()
 print("结束调用test")
 next(res)
 next(res)

输出:

开始调用test
结束调用test
第一次next(res)
进入test函数
yield number 0
第二次next(res)
yield number  1

从结果可以看出,只有使用next调用迭代器时(使用for,while循环也可以),才会去执行迭代器函数中的内容。

python中生成器可以分为生成器函数和生成器表达式,生成器函数和生成器表达式是两种不同的类型。

生成器函数是一个函数体中有yield关键字的,我们上面定义的test就是生成器函数。

生成器表达式的使用比较受限制,一个生成器表达式返回一个生成器。下面是一个使用生成器表达式的案例:

squares = (x * x for x in range(1,10))
print(type(squares))
print(list(squares))

输出:

<class 'generator'>
[1, 4, 9, 16, 25, 36, 49, 64, 81]

生成器的效率是非常高的,生成器可以更好的利用内存和CPU的使用效率,并且通常生成器的代码都比较少,这使用生成器的代码非常好容易理解。应此应该尽量多的在代码中使用生成器

参考文档

https://www.datacamp.com/community/tutorials/python-iterator-tutorial

总结

以上所述是小编给大家介绍的Python中的迭代器,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Python 相关文章推荐
Python生成随机数的方法
Jan 14 Python
Flask入门教程实例:搭建一个静态博客
Mar 27 Python
python实现爬取千万淘宝商品的方法
Jun 30 Python
python构建自定义回调函数详解
Jun 20 Python
33个Python爬虫项目实战(推荐)
Jul 08 Python
Python字符串、列表、元组、字典、集合的补充实例详解
Dec 20 Python
python实现多进程按序号批量修改文件名的方法示例
Dec 30 Python
Python中os模块功能与用法详解
Feb 26 Python
Keras设置以及获取权重的实现
Jun 19 Python
使用python修改文件并立即写回到原始位置操作(inplace读写)
Jun 28 Python
python海龟绘图之画国旗实例代码
Nov 11 Python
Python - 10行代码集2000张美女图
May 23 Python
Python学习笔记之读取文件、OS模块、异常处理、with as语法示例
Jun 04 #Python
Python利用sqlacodegen自动生成ORM实体类示例
Jun 04 #Python
Python批量生成幻影坦克图片实例代码
Jun 04 #Python
python和mysql交互操作实例详解【基于pymysql库】
Jun 04 #Python
Python获取基金网站网页内容、使用BeautifulSoup库分析html操作示例
Jun 04 #Python
Python使用MyQR制作专属动态彩色二维码功能
Jun 04 #Python
Python流行ORM框架sqlalchemy安装与使用教程
Jun 04 #Python
You might like
迅雷下载《中学科技》怀旧期刊下载
2021/02/27 无线电
一篇入门的php Class 文章
2007/04/04 PHP
在php中判断一个请求是ajax请求还是普通请求的方法
2011/06/28 PHP
PHP+JavaScript实现无刷新上传图片
2017/02/21 PHP
PHP使用PDO调用mssql存储过程的方法示例
2017/10/07 PHP
微信小程序发送订阅消息的方法(php 为例)
2019/10/30 PHP
javascript中&quot;/&quot;运算符常见错误
2010/10/13 Javascript
跨浏览器的事件对象介绍
2012/06/27 Javascript
JS性能优化笔记搜索整理
2013/08/21 Javascript
jQuery.deferred对象使用详解
2016/03/18 Javascript
jquery 判断div show的状态实例
2016/12/03 Javascript
JS如何生成一个不重复的ID的函数
2016/12/25 Javascript
Bootstrap的modal拖动效果
2016/12/25 Javascript
Javascript中构造函数要注意的一些坑
2017/01/23 Javascript
jQuery实现优雅的弹窗效果(6)
2017/02/08 Javascript
使用jQuery和ajax代替iframe的方法(详解)
2017/04/12 jQuery
jquery中封装函数传递当前元素的方法示例
2017/05/05 jQuery
js实现随机点名系统(实例讲解)
2017/10/18 Javascript
Node.js一行代码实现静态文件服务器的方法步骤
2019/05/07 Javascript
[49:29]LGD vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
[42:52]Optic vs Serenity 2018国际邀请赛淘汰赛BO3 第二场 8.22
2018/08/23 DOTA
netbeans7安装python插件的方法图解
2013/12/24 Python
Python中__init__和__new__的区别详解
2014/07/09 Python
详解python脚本自动生成需要文件实例代码
2017/02/04 Python
python语言中有算法吗
2020/06/16 Python
Python工程师必考的6个经典面试题
2020/06/28 Python
css3圆角样式分享自定义按钮样式
2013/12/27 HTML / CSS
HTML5 播放 RTSP 视频的实例代码
2019/07/29 HTML / CSS
阿迪达斯俄罗斯官方商城:adidas俄罗斯
2017/03/08 全球购物
美国在线购物频道:Shop LC
2019/04/21 全球购物
活动志愿者自荐信
2014/01/27 职场文书
师德师风个人自我剖析材料
2014/09/27 职场文书
宿舍管理制度范本
2015/08/07 职场文书
《确定位置》教学反思
2016/02/18 职场文书
解决Mysql报错 Table 'mysql.user' doesn't exist
2022/05/06 MySQL
SQL Server中搜索特定的对象
2022/05/25 SQL Server