当前位置: 首页 > news >正文

python -迭代器与生成器 以及 iterable(可迭代对象)、yield语句

我刚开始学习编程没多久,对于很多知识还完全不知道,而有些知道的也是一知半解,我想把学习到的知识记录下来,一是弥补记忆力差的毛病,二也是为了待以后知识能进一步理解透彻时再回来做一个补充。

参考链接:

  完全理解 Python 迭代对象、迭代器、生成器:http://python.jobbole.com/87805/

 

一、迭代器(iterator)

  参考链接:http://www.runoob.com/python3/python3-iterator-generator.html

  迭代是Python最强大的功能之一,是访问集合元素的一种方式。迭代器是一个对象,是一个可以记住遍历位置的对象,或者说是一个带状态的对象,他能在你调用 next() 方法的时候返回容器中的下一个值,(我的理解是这个状态与next有关,代表当前处于哪个位置)

  迭代器对象(把人比作迭代器,那么迭代器对象就是小明,不要笑,要不本人理解不清楚)从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。

  迭代器就像一个懒加载的工厂,等到有人需要的时候才给它生成值返回,没调用的时候就处于休眠状态等待下一次调用。

  创建迭代器对象:

  字符串,列表或元组对象都可用于创建迭代器:

>>>list=[1,2,3,4]
>>> it = iter(list)    # 创建迭代器对象

  迭代器有两个基本的方法:iter() 和 next(),可以使用next或者for循环进行遍历

  创建一个迭代器:(不是迭代器对象)

  把一个类作为一个迭代器使用需要在类中实现两个方法 __iter__() 与 __next__() 。

  如果你已经了解的面向对象编程,就知道类都有一个构造函数,Python 的构造函数为 __init__(), 它会在对象初始化的时候自动调用

  __iter__() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 __next__() 方法并通过 StopIteration 异常标识迭代的完成。

  __next__() 方法(Python 2 里是 next())会返回下一个迭代器对象。

  StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况,在 __next__() 方法中我们可以设置在完成指定循环次数后触发 StopIteration 异常使用 raise 语句来结束迭代。

  迭代器持有一个内部状态的字段,用于记录下次迭代返回值,它实现了__next__和__iter__方法(我的理解是迭代器是一个称号,就像英语证书一样,你通过考试(这里是实现两个功能即)才能拿到证书),迭代器不会一次性把所有元素加载到内存,而是需要的时候才生成返回结果。

  

二、可迭代对象iterable

  iterable--是在学习yield语句时看到一篇博客了解到的:http://www.runoob.com/w3cnote/python-yield-used-analysis.html

  作者写的非常好,为了让读者更透彻的理解yield语句的功能和特点,他循序渐进的对一个程序进行了多次改进,有一小节就提到了iterable。经过初步的学习,我还没有理解这是个啥?甚至连它是一个数据类型还是方法都没搞清楚,不管这样,先把学习到的知识记录下来吧!待以后再慢慢理解

  但凡是可以返回一个迭代器的对象都可称之为可迭代对象,可迭代对象和容器一样是一种通俗的叫法,并不是指某种具体的数据类型

  具有 iterable 类型的集合可以通过新的 for ... of 循环来遍历。

   for ... of 好像是JavaScript语言里面的

   for ... in 循环由于历史遗留问题,它遍历的实际上是对象的属性名称。一个 Array 数组实际上也是一个对象,它的每个元素的索引被视为一个属性。

  当我们手动给 Array 对象添加了额外的属性后, for ... in 循环将带来意想不到的意外效果:

var a = ['A', 'B', 'C'];
a.name = 'Hello';
for (var x in a) {
    console.log(x); // '0', '1', '2', 'name'
}

  

   for ... in 循环将把 name 包括在内,但 Array 的 length 属性却不包括在内。

   for ... of 循环则完全修复了这些问题,它只循环集合本身的元素:

var a = ['A', 'B', 'C'];
a.name = 'Hello';
for (var x of a) {
    console.log(x); // 'A', 'B', 'C'
}

   然而,更好的方式是直接使用 iterable 内置的 forEach 方法,它接收一个函数,每次迭代就自动回调该函数。以 Array 为例:

'use strict';
var a = ['A', 'B', 'C'];
a.forEach(function (element, index, array) {#每次迭代就回调function
    // element: 指向当前元素的值
    // index: 指向当前索引
    // array: 指向Array对象本身
    console.log(element + ', index = ' + index);
});
#输出
A, index = 0
B, index = 1
C, index = 2

  Map和Set的回调函数的参数见链接:https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/00143450082788640f82a480be8481a8ce8272951a40970000

 

三、生成器generator

  yield语句

  在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。

  yield语句使用:http://www.runoob.com/w3cnote/python-yield-used-analysis.html(先看结论)

  参考链接:https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/00138681965108490cb4c13182e472f8d87830f13be6e88000

  把python中一边循环一边按照规律计算下一个的机制叫做生成器

  生成器是一个返回迭代器的函数

  创建生成器的两个办法:一个是列表生成式、一个是将使用yield语句将函数变成生成器

  列表生成式方法:

  用来解决一个较大的列表却每次只使用其中一个元素造成内存浪费的问题

  用函数来实现生成器:

  如果推算的算法比较复杂,类似列表生成式的for循环无法实现的时候,还可以用函数来实现。如果一个函数定义中包含 yield 关键字,那么这个函数就不再是一个普通函数,而是一个generator。

  我们在循环过程中不断调用 yield ,就会不断中断。当然要给循环设置一个条件来退出循环,不然就会产生一个无限数列出来。

  例子见链接

  generator保存的是算法,每次调用 next() ,(其实是每次迭代的时候就像是调用next)就计算出下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

  这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用 next() 的时候执行,遇到 yield (while True语句是也是这个意思,我刚开始没有拐过来弯)语句返回,再次执行时从上次返回的 yield 语句处继续执行。

  我把它理解为使用 next() 来调用生成器(看成是一次计算),但更好的办法是通过for循环来进行迭代

   generator是非常强大的工具,在Python中,可以简单地把列表生成式改成generator,也可以通过函数实现复杂逻辑的generator。

  生成器是一种特殊的迭代器,它的返回值不是通过 return 而是用 yield 。

  要理解generator的工作原理,它是在 for 循环的过程中不断计算出下一个元素,并在适当的条件结束 for 循环。对于函数改成的generator来说,遇到return语句或者执行到函数体最后一行语句,就是结束generator的指令, for 循环随之结束。

 

四、容器

  参考链接:http://python.jobbole.com/87805/

  容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用innot in关键字判断元素是否包含在容器中。容器比较容易理解,因为你就可以把它看作是一个盒子、一栋房子、一个柜子,里面可以塞任何东西。从技术角度来说,当它可以用来询问某个元素是否包含在其中时,那么这个对象就可以认为是一个容器,比如 list,set,tuples都是容器对象

  尽管绝大多数容器都提供了某种方式来获取其中的每一个元素,但这并不是容器本身提供的能力,而是可迭代对象赋予了容器这种能力

 

五、xrange和range的区别

  参考链接:http://ciniao.me/article.php?id=17

  只有在python2中有区别,python3中没有了

  xrange生成的不是一个数组,而是一个生成器(关于生成器我也不清楚,猜测是只有使用时才会生成)

>>> xrange(5)
xrange(5)
>>> list(xrange(5))
[0, 1, 2, 3, 4]
>>> xrange(1,5)
xrange(1, 5)#不立即生成,只有使用时会生成
>>> list(xrange(1,5))
[1, 2, 3, 4]
>>> xrange(0,6,2)
xrange(0, 6, 2)
>>> list(xrange(0,6,2))
[0, 2, 4]

  range会直接生成一个列表,而xrange不是这样,只在每次调用时返回一个值,所以要生成很大的数字序列的时候,用xrange会比range性能优很多,因为不需要一上来就开辟一块很大的内存空间。

转载于:https://www.cnblogs.com/Gaoqiking/p/10573634.html

相关文章:

  • LeetCode.914 卡牌分组
  • 本周学习小结(25/03 - 31/03)
  • Beetl 提供俩种方式来显示实现局部更新
  • core_framework —— 基于libev的轻量级lua网络开发框架
  • MyCAT水平分库
  • 织梦CMS模板中dede标签使用php和if判断语句的方法
  • 2019第十四届中国竞争情报国际年会将于4月在上海召开
  • 移动互联网下半场,iOS开发者如何“高薪”成长?
  • 判断是手机端还是PC端的代码
  • linux分区方案
  • 邮件加密之SMIME
  • 微信公众平台生成二维码海报是如何做到的?
  • idea thymeleaf 表达式模板报红波浪线
  • 呼叫中心系统常见的数据对接接口方式
  • JAVA8给我带了什么——lambda表达
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • ECS应用管理最佳实践
  • exif信息对照
  • git 常用命令
  • magento2项目上线注意事项
  • rabbitmq延迟消息示例
  • SQLServer之创建显式事务
  • 给自己的博客网站加上酷炫的初音未来音乐游戏?
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 容器服务kubernetes弹性伸缩高级用法
  • 体验javascript之美-第五课 匿名函数自执行和闭包是一回事儿吗?
  • 微信小程序实战练习(仿五洲到家微信版)
  • 移动端唤起键盘时取消position:fixed定位
  • 掌握面试——弹出框的实现(一道题中包含布局/js设计模式)
  • 做一名精致的JavaScripter 01:JavaScript简介
  • Spring第一个helloWorld
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • ​HTTP与HTTPS:网络通信的安全卫士
  • ​如何在iOS手机上查看应用日志
  • #define用法
  • (11)MATLAB PCA+SVM 人脸识别
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • (Matlab)遗传算法优化的BP神经网络实现回归预测
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (编程语言界的丐帮 C#).NET MD5 HASH 哈希 加密 与JAVA 互通
  • (超简单)构建高可用网络应用:使用Nginx进行负载均衡与健康检查
  • (超简单)使用vuepress搭建自己的博客并部署到github pages上
  • (大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量
  • (动态规划)5. 最长回文子串 java解决
  • (转) 深度模型优化性能 调参
  • (转)http协议
  • (转)视频码率,帧率和分辨率的联系与区别
  • .net Signalr 使用笔记
  • .NET的数据绑定
  • .one4-V-XXXXXXXX勒索病毒数据怎么处理|数据解密恢复
  • [ 云计算 | AWS 实践 ] Java 如何重命名 Amazon S3 中的文件和文件夹
  • [ARM]ldr 和 adr 伪指令的区别
  • [AutoSar]BSW_Memory_Stack_004 创建一个简单NV block并调试
  • [bzoj1324]Exca王者之剑_最小割
  • [codevs 1515]跳 【解题报告】