深入浅析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的Django框架测试驱动开发的教程
Apr 22 Python
python遍历序列enumerate函数浅析
Oct 17 Python
Python数据类型中的“冒号“[::]——分片与步长操作示例
Jan 24 Python
pyqt5的QComboBox 使用模板的具体方法
Sep 06 Python
python实现最小二乘法线性拟合
Jul 19 Python
详解python播放音频的三种方法
Sep 23 Python
python实现回旋矩阵方式(旋转矩阵)
Dec 04 Python
根据tensor的名字获取变量的值方式
Jan 04 Python
Django模板获取field的verbose_name实例
May 19 Python
django rest framework 过滤时间操作
Jul 12 Python
Django3中的自定义用户模型实例详解
Aug 23 Python
Python使用pickle进行序列化和反序列化的示例代码
Sep 22 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
PHP中用正则表达式清除字符串的空白
2011/01/17 PHP
PHP使用HTML5 FileApi实现Ajax上传文件功能示例
2019/07/01 PHP
关于实现代码语法标亮 dp.SyntaxHighlighter
2007/02/02 Javascript
Firefox outerHTML实现代码
2009/06/04 Javascript
Javascript 圆角div的实现代码
2009/10/15 Javascript
基于jQuery实现网页进度显示插件
2015/03/04 Javascript
javascript实现了照片拖拽点击置顶的照片墙代码
2015/04/03 Javascript
javascript模拟评分控件实现方法
2015/05/13 Javascript
jQuery移动web开发中的页面初始化与加载事件
2015/12/03 Javascript
Vue.js 表单校验插件
2016/08/14 Javascript
Vue下的国际化处理方法
2017/12/18 Javascript
编写React组件项目实践分析
2018/03/04 Javascript
layui的table中显示图片方法
2018/08/17 Javascript
基于Layui自定义模块的使用方法详解
2019/09/14 Javascript
JS call()及apply()方法使用实例汇总
2020/07/11 Javascript
[27:08]完美世界DOTA2联赛PWL S2 SZ vs Rebirth 第二场 11.21
2020/11/23 DOTA
一个基于flask的web应用诞生 记录用户账户登录状态(6)
2017/04/11 Python
Python安装官方whl包和tar.gz包的方法(推荐)
2017/06/04 Python
python批量识别图片指定区域文字内容
2019/04/30 Python
Python爬取智联招聘数据分析师岗位相关信息的方法
2019/08/13 Python
Python+OpenCv制作证件图片生成器的操作方法
2019/08/21 Python
Python中输入和输出(打印)数据实例方法
2019/10/13 Python
django model object序列化实例
2020/03/13 Python
CSS3中的@keyframes关键帧动画的选择器绑定
2016/06/13 HTML / CSS
Fairyseason:为个人和批发商提供女装和配件
2017/03/01 全球购物
迪卡侬波兰体育用品商店:Decathlon波兰
2020/03/31 全球购物
空字符串(“”)和null的区别
2012/11/13 面试题
AJAX检测用户名是否存在的方法
2021/03/24 Javascript
迟到检讨书500字
2014/02/05 职场文书
金融保险专业求职信
2014/09/03 职场文书
大一工商管理职业生涯规划:有梦最美,行动相随
2014/09/18 职场文书
老人与海读书笔记
2015/06/26 职场文书
小型企业的绩效考核制度模板
2019/11/21 职场文书
golang通过递归遍历生成树状结构的操作
2021/04/28 Golang
SQL Server表分区删除详情
2021/10/16 SQL Server
JavaScript 事件捕获冒泡与捕获详情
2021/11/11 Javascript