Python生成器generator原理及用法解析


Posted in Python onJuly 20, 2020

前言

生成器generator

生成器的本质是一个迭代器(iterator)

要理解生成器,就要在理解一下迭代,可迭代对象,迭代器,这三个概念

Python生成器generator简介

iteration, iterable, iterator

迭代(iteration):在python中迭代通常是通过for...in...来实现的.而且只要是可迭代对象iterable,都能进行迭代.

可迭代对象(iterable):Python中的任意的对象,只要它定义了可以返回一个迭代器的 __iter__方法,或者定义了可以支持下标索引的__getitem __方法,那么它就是一个可迭代对象。简单说,可迭代对象就是能提供迭代器的任意对象.返回的是一个iterator 对象.官方解释

迭代器(iterator ) : 简单的说,迭代器就是实现了iterator.__iter__() 和iterator.__next__() 的对象,iterator.__iter__()方法返回的是iterator对象本身.根据官方的说法,正是这个方法,实现了for ... in ...语句.而iterator.__next__()是iterator区别于iterable的关键了,它允许我们显式地获取一个元素.当调用next()方法时,实际上产生了2个操作:

更新iterator状态,令其指向后一项,以便下一次调用,每一个值过后,指针移动到下一位,对iterator遍历完后,其变成了一个空的容器,但不是None ,需要注意的是,迭代结束后,指针不会自动返回到首位,而是依旧停留在末位置,想要在开始,需要重新载入迭代对象.

实例理解:

>>> from collections import Iterable, Iterator
 >>> a = [1,2,3]  # 众所周知,list是一个iterable
 >>> b = iter(a)  # 通过iter()方法,得到iterator,iter()实际上调用了__iter__(),
 >>> isinstance(a, Iterable)
 True
 >>> isinstance(a, Iterator)
 False
 >>> isinstance(b, Iterable)
 True
 >>> isinstance(b, Iterator)
 True

可见,itertor 一定是iterable ,但iterable不一定是itertor

>>> dir(a)
 ['__add__','__class__','__contains__','__delattr__','__delitem__','__dir__','__doc__','__eq__','__format__','__ge__','__getattribute__','__getitem__','__gt__','__hash__','__iadd__','__imul__','__init__','__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']
 
 >>>dir(b)
 ['__class__','__delattr__', '__dir__', '__doc__','__eq__', '__format__','__ge__' ,'__getattribute__', '__gt__','__hash__','__init__','__iter__','__le__','__length_hint__',
 '__lt__','__ne__','__new__','__next__','__reduce__','__reduce_ex__','__repr__','__setattr__', '__setstate__','__sizeof__','__str__','__subclasshook__']

可以看到迭代器具有__next__ 这个方法,可迭代对象具有__getitem__

迭代器是消耗型的,随着指针的移动,遍历完毕以后,就为空,但是不是None

>>> c = list(b)
 >>> c
 [1, 2, 3]
 >>> d = list(b)
 >>> d
 []
 
 
 # 空的iterator并不等于None.
 >>> if b:
 ...  print(1)
 ...
 1
 >>> if b == None:
 ...  print(1)
 ...

使用迭代器的内置方法 __next__ 和 next() 方法,遍历元素

In [73]: e = iter(a)
 
 In [74]: next(e)
 Out[74]: 1
 
 In [75]: e.__next__
 Out[75]: <method-wrapper '__next__' of list_iterator object at 0x7f05571c8518>
 
 In [76]: e.__next__()
 Out[76]: 2
 
 In [77]: e.__next__()
 Out[77]: 3
 
 In [78]: e.__next__()
 ---------------------------------------------------------------------------
 StopIteration               Traceback (most recent call last)
 <ipython-input-78-6024b5bd9bd2> in <module>()
 ----> 1 e.__next__()
 StopIteration:

当遍历完毕时,会返回一个StopIteration 的错误.

for...in.... 遍历迭代

当我们对一个iterable 使用for ....in... 进行遍历时,实际上是想调用iter() 方法得到一个iterator ,假设为x ,然后循环的调用x 的__next__() (next())方法,取得每一次的值,直到iterator为空,返回StopIteration 作为循环的结束的标准.for....in...会自动处理 StopIteration 异常,从而避免了抛出异常,从而使程序中断.流程图为:

x = [1, 2, 3]
for i in x:
print(x)

Python生成器generator原理及用法解析

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
纯Python开发的nosql数据库CodernityDB介绍和使用实例
Oct 23 Python
Python heapq使用详解及实例代码
Jan 25 Python
Selenium的使用详解
Oct 19 Python
python实现在图片上画特定大小角度矩形框
Oct 24 Python
Python微医挂号网医生数据抓取
Jan 24 Python
完美解决Python matplotlib绘图时汉字显示不正常的问题
Jan 29 Python
Python requests模块实例用法
Feb 11 Python
Python之时间和日期使用小结
Feb 14 Python
在Python中如何传递任意数量的实参的示例代码
Mar 21 Python
python使用opencv对图像mask处理的方法
Jul 05 Python
python如何安装下载后的模块
Jul 03 Python
解决python运行效率不高的问题
Jul 20 Python
Win10环境中如何实现python2和python3并存
Jul 20 #Python
python和go语言的区别是什么
Jul 20 #Python
Python基础教程(一)——Windows搭建开发Python开发环境
Jul 20 #Python
Python字典fromkeys()方法使用代码实例
Jul 20 #Python
Python爬虫设置ip代理过程解析
Jul 20 #Python
Python如何使用27行代码绘制星星图
Jul 20 #Python
tensorflow基于CNN实战mnist手写识别(小白必看)
Jul 20 #Python
You might like
PHP读取目录下所有文件的代码
2008/01/07 PHP
PHP利用str_replace防注入的方法
2013/11/10 PHP
PHP捕获Fatal error错误的方法
2014/06/11 PHP
destoon在360浏览器下出现用户被强行注销的解决方法
2014/06/26 PHP
9个经典的PHP代码片段分享
2014/12/18 PHP
CodeIgniter扩展核心类实例详解
2016/01/20 PHP
php使用pear_smtp发送邮件
2016/04/15 PHP
thinkPHP批量删除的实现方法分析
2016/11/09 PHP
php使用scandir()函数扫描指定目录下所有文件示例
2019/06/08 PHP
php+jQuery ajax实现的实时刷新显示数据功能示例
2019/09/12 PHP
php设计模式之模板模式实例分析【星际争霸游戏案例】
2020/03/24 PHP
Javascript中的Split使用方法与技巧
2007/03/09 Javascript
超级简单的图片防盗(HTML),好用
2007/04/08 Javascript
Javascript 实现复制(Copy)动作方法大全
2014/06/20 Javascript
jquery实现鼠标悬浮停止轮播特效
2020/08/20 Javascript
学习JavaScript设计模式之责任链模式
2016/01/18 Javascript
BootStrap点击下拉菜单项后显示一个新的输入框实现代码
2016/05/16 Javascript
微信小程序 页面传值详解
2017/03/10 Javascript
利用node.js如何搭建一个简易的即时响应服务器
2017/05/28 Javascript
基于angular2 的 http服务封装的实例代码
2017/06/29 Javascript
PostgreSQL Node.js实现函数计算方法示例
2019/02/12 Javascript
JS浅拷贝和深拷贝原理与实现方法分析
2019/02/28 Javascript
通过Nodejs搭建网站简单实现注册登录流程
2019/06/14 NodeJs
Layer+Echarts构建弹出层折线图的方法
2019/09/25 Javascript
浅谈鸿蒙 JavaScript GUI 技术栈
2020/09/17 Javascript
node.js如何根据URL返回指定的图片详解
2020/10/21 Javascript
[01:06:18]DOTA2-DPC中国联赛 正赛 Phoenix vs Dynasty BO3 第二场 1月26日
2021/03/11 DOTA
Python实现端口复用实例代码
2014/07/03 Python
pytorch 实现在预训练模型的 input上增减通道
2020/01/06 Python
英国翻新电子产品购物网站:Tech Trade
2017/12/25 全球购物
《在家里》教后反思
2014/03/01 职场文书
2014年科协工作总结
2014/12/09 职场文书
中国汉字听写大会观后感
2015/06/02 职场文书
MySQL 使用事件(Events)完成计划任务
2021/05/24 MySQL
浅谈MySQL中的六种日志
2022/03/23 MySQL
Python turtle编写简单的球类小游戏
2022/03/31 Python