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爬虫之抓取百度贴吧并存储到本地txt文件改进版
Nov 06 Python
python获取当前计算机cpu数量的方法
Apr 18 Python
总结Python中逻辑运算符的使用
May 13 Python
Python使用lxml模块和Requests模块抓取HTML页面的教程
May 16 Python
python取代netcat过程分析
Feb 10 Python
Python3中详解fabfile的编写
Jun 24 Python
Python使用cx_Freeze库生成msi格式安装文件的方法
Jul 10 Python
kaggle+mnist实现手写字体识别
Jul 26 Python
使用Python在Windows下获取USB PID&amp;VID的方法
Jul 02 Python
python3中替换python2中cmp函数的实现
Aug 20 Python
pycharm 中mark directory as exclude的用法详解
Feb 14 Python
Python实现对adb命令封装
Mar 06 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
DOTA2游戏同人动画《龙之血》导演接受采访
2021/03/05 欧美动漫
举例详解PHP脚本的测试方法
2015/08/05 PHP
php基于Redis消息队列实现的消息推送的方法
2018/11/28 PHP
PHP PDOStatement::getAttribute讲解
2019/02/01 PHP
Smarty模板类内部原理实例分析
2019/07/03 PHP
JavaScript Konami Code 实现代码
2009/07/29 Javascript
XMLHttpRequest处理xml格式的返回数据(示例代码)
2013/11/21 Javascript
Jquery操作js数组及对象示例代码
2014/05/11 Javascript
分享33个jQuery与CSS3实现的绚丽鼠标悬停效果
2014/12/15 Javascript
深入解析jQuery中Deferred的deferred.promise()方法
2016/05/03 Javascript
JavaScript制作简单的框选图表
2017/05/15 Javascript
node.js通过axios实现网络请求的方法
2018/03/05 Javascript
vue自定义指令的创建和使用方法实例分析
2018/12/04 Javascript
使用watch在微信小程序中实现全局状态共享
2019/06/03 Javascript
微信小程序中如何使用flyio封装网络请求
2019/07/03 Javascript
redux处理异步action解决方案
2020/03/22 Javascript
react PropTypes校验传递的值操作示例
2020/04/28 Javascript
解决Pycharm 包已经下载,但是运行代码提示找不到模块的问题
2019/08/31 Python
pymysql 插入数据 转义处理方式
2020/03/02 Python
在keras 中获取张量 tensor 的维度大小实例
2020/06/10 Python
python获取本周、上周、本月、上月及本季的时间代码实例
2020/09/08 Python
python报错TypeError: ‘NoneType‘ object is not subscriptable的解决方法
2020/11/05 Python
Python join()函数原理及使用方法
2020/11/14 Python
HTML5 CSS3给网站设计带来出色效果
2009/07/16 HTML / CSS
canvas生成带二维码海报的踩坑记录
2019/09/11 HTML / CSS
Bose法国官网:购买耳机、扬声器、家庭影院、专业音响
2017/12/21 全球购物
速比涛英国官网:Speedo英国
2019/07/15 全球购物
澳洲网红粉泥面膜:Sand & Sky
2019/08/13 全球购物
大学四年个人的自我评价
2014/02/26 职场文书
会议主持词
2014/03/17 职场文书
讲座主持词
2014/03/20 职场文书
十佳文明家庭事迹
2014/05/25 职场文书
体育专业大学生职业生涯规划范文:打造自己的运动帝国
2014/09/12 职场文书
可怜妈妈观后感
2015/06/09 职场文书
高中政治教学反思
2016/02/23 职场文书
Mysql数据库事务的脏读幻读及不可重复读详解
2022/05/30 MySQL