week3 day3 迭代器和生成器

  • 一. 迭代器
    • 1.1 什么是迭代器?
    • 1.2 为何要使用迭代器?
    • 1.3 如何使用迭代器?
    • 1.4 迭代器例子
    • 1.5 for循环的原理
    • 1.6 迭代器的优缺点
      • 1.6.1 迭代器优点
      • 1.6.2 迭代器缺点
  • 二. 生成器
    • 2.1 什么是生成器?
    • 2.2 为何要用生成器?
    • 2.3 怎么使用生成器?
    • 2.4 yield表达式的应用

一. 迭代器

我们之前在学习流程控制的时候学习过for循环,那么for循环的内在工作原理是什么呢?今天,我们将先来探讨for循环的工作原理。

迭代器即用来迭代取值的工具,而迭代是重复反馈的活动,其目的通常是为了逼近所需的目标或者结果。每一次对过程的重复称为一次迭代,而每一次迭代得到的结果会作为下一次迭代的初始值,单纯的重复并不是迭代。

while True:msg = input('>>: ').strip()print(msg)

下述while循环才是一个迭代过程,不仅满足重复,而且以每次重新赋值后的index值作为下一次循环中新的索引进行取值,反复迭代,最终可以取尽列表中的值

goods=['mac','lenovo','acer','dell','sony']index=0
while index < len(goods):print(goods[index])index+=1

1.1 什么是迭代器?

迭代器:迭代取值的工具。
什么是迭代:迭代的基础是重复,但是每次重复都是在上一次基础上进行的。

1.2 为何要使用迭代器?

  1. 迭代器提供了一种不依赖于索引的通用的可以取值的方法。
  2. 节省内存。

1.3 如何使用迭代器?

可迭代对象:含有__iter__方法的对象。

当可迭代对象调用__iter__方法的时候,返回一个迭代器对象。

我们所学习的数据类型中,有很多数据类型都有内置的__iter__方法。

''.__iter__()
[].__iter__()
().__iter__()
{}.__iter__()
{}.__iter__()
f=open(r'a.txt',mode='rb')
f.__iter__()
f.__next__()

我们发现字符串,列表,元组,字典,集合文件都有python解释器内置的iter方法,而文件不止有iter方法,还有next方法。

迭代器对象:含有__iter__和__next__方法的对象。

当迭代器对象调用__iter__方法的时候,返回的是它自己。
当迭代器对象调用__next__方法的时候,拿到的是下一个值。
可以一直使用__next__方法取下一个值,直到抛出异常StopIteration。

1.4 迭代器例子

nums=[11,22,33,44,55]
nums_iter=nums.__iter__() or nums_iter=iter(nums) # 拿到迭代器对象
print(nums_iter.__next__()) / print(next(nums_iter))----->11
print(nums_iter.__next__()) / print(next(nums_iter))----->22
print(nums_iter.__next__()) / print(next(nums_iter))----->33
print(nums_iter.__next__()) / print(next(nums_iter))----->44
print(nums_iter.__next__()) / print(next(nums_iter))----->55
print(nums_iter.__next__()) / print(next(nums_iter))----->StopIteration

1.5 for循环的原理

有了迭代器之后,我们便可以不依赖索引迭代取值了,使用while循环的实现方式如下:

goods=['mac','lenovo','acer','dell','sony']
i=iter(goods) #每次都需要重新获取一个迭代器对象
while True:try:print(next(i))except StopIteration: #捕捉异常终止循环break

for循环又称迭代循环,in后可以跟任何可迭代对象,上述while循环可以简写为:

goods=['mac','lenovo','acer','dell','sony']
for item in goods:   print(item)

for循环在工作时,首先会调用可迭代对象goods内置的iter方法拿到一个迭代器对象,然后再调用该迭代器对象的next方法,将取到的值赋给item,执行循环体完成一次循环,周而复始,知道捕捉StopIteration异常,结束迭代。

1.6 迭代器的优缺点

基于索引的迭代取值,所有迭代状态都保存在了索引中,而基于迭代器实现迭代的方式不再需要索引,所有迭代的状态就保存在迭代器中,然而这种处理方式优点与缺点并存:

1.6.1 迭代器优点

  1. 为序列和非序列类型提供了统一的迭代取值方式。
  2. 惰性计算:迭代器对象表示的是一个数据流,可以只在需要时才去调用next来计算出一个值,就迭代器本身来说,同一时刻在内存中只有一个值,因而可以存放无限大的数据流,而对于其他容器类型数据,如列表,需要把所有的元素都存放于内存中,受内存大小的限制,可以存放的个数是有限的。

1.6.2 迭代器缺点

  1. 除非取尽,否则无法获取迭代器的长度
  2. 只能取到下一个值,不能回到开始,更像是“一次性的”,迭代器产生后的唯一目标就是重复执行next方法直到值取尽,否则就会停留在某个位置,等待下一次调用next;若是要再次迭代同个对象,你只能重新调用iter方法创建一个新的迭代器对象,如果有两个或者多个循环使用同一个迭代器,必然只会有一个循环能取到值。

二. 生成器

迭代器的有一个优点是节约内存,但现在我们进行的操作一直是将某个已经占据了内存的数据转换成迭代器对象,然后遍历取值,但是如何才能发挥迭代器节约内存的优点呢?如果我们可以自定义迭代器,那么是不是就可以节约内存呢?

2.1 什么是生成器?

生成器就是自定义的迭代器。

2.2 为何要用生成器?

可以自定义迭代的范围,节省内存。

2.3 怎么使用生成器?

我们之前学过return,return可以让我们拿到函数的返回值,但是同时,函数体遇到return将终止后续代码的运行。因此,需要一个可以拿到返回值,但不会终止函数运行的东西,这就是yield。若函数体包含yield关键字,再调用函数,并不会执行函数体代码,得到的返回值即生成器对象:

def func():print(111)yield 1print(222)yield 2print(333)yield 3
func() # --->空

当函数中出现yield时,因为yield的存在,调用函数不会直接运行函数。但是我们前面说过yield是可以返回值的,因此,我们打印一下运行func()的返回值看一下:

res=func()
print(res) # ---><generator object func at 0x00000231C367C5C8>

我们发现虽然函数体没有运行,但我们得到了一个生成器,我们之前说过生成器就是一个自定义的迭代器,那么迭代器的内置方法生成器一定都有!

func_iter=iter(func())
res1=next(func_iter)----->111 # res1拿到的是第一个yield的值。next方法可以运行到第一个yield挂起
print(res1)----->1
res2=next(func_iter)----->222 # res2拿到的是第二个yield的值。next方法可以运行到第二个yield挂起
print(res2)----->2
res3=next(func_iter)----->333 # res3拿到的是第三个yield的值。next方法可以运行到第三个yield挂起
print(res3)----->3

有了yield关键字,我们就有了一种自定义迭代器的实现方式。yield可以用于返回值,但不同于return,函数一旦遇到return就结束了,而yield可以保存函数的运行状态挂起函数,用来返回多次值

2.4 yield表达式的应用

在函数内可以采用表达式形式的yield:

def eater():print('Ready to eat')while True:food=yieldprint('get the food: %s, and start to eat' %food)

可以拿到函数的生成器对象持续为函数体send值(给yield传值),如下:

>>> g=eater() # 得到生成器对象
>>> g
<generator object eater at 0x101b6e2b0>
>>> next(e) # 需要事先”初始化”一次,让函数挂起在food=yield,等待调用g.send()方法为其传值
Ready to eat
>>> g.send('包子') # 给yield传值
get the food: 包子, and start to eat
>>> g.send('鸡腿') # 给yield传值
get the food: 鸡腿, and start to eat

针对表达式形式的yield,生成器对象必须事先被初始化一次,让函数挂起在food=yield位置,等待调用g.send(value)方法为函数体传值,g.send(None)等同于next(g)

我们可以编写装饰器来完成为所有表达式形式yield对应生成器的初始化操作,如下:

def init(func):def wrapper(*args,**kwargs):g=func(*args,**kwargs)next(g)return greturn wrapper@init
def eater():print('Ready to eat')while True:food=yieldprint('get the food: %s, and start to eat' %food)

表达式形式的yield也可以用于返回多次值,即变量名=yield值的形式,如下:

>>> def eater():
...     print('Ready to eat')
...     food_list=[]
...     while True:
...         food=yield food_list
...         food_list.append(food)
...
>>> e=eater()
>>> next(e)
Ready to eat
[]
>>> e.send('蒸羊羔')
['蒸羊羔']
>>> e.send('蒸熊掌')
['蒸羊羔', '蒸熊掌']
>>> e.send('蒸鹿尾儿')
['蒸羊羔', '蒸熊掌', '蒸鹿尾儿']

week3 day3 迭代器和生成器相关推荐

  1. 完全理解Python迭代对象、迭代器、生成器

    本文源自RQ作者的一篇博文,原文是Iterables vs. Iterators vs. Generators,俺写的这篇文章是按照自己的理解做的参考翻译,算不上是原文的中译版本,推荐阅读原文,谢谢网 ...

  2. Python学习笔记3 流程控制、迭代器、生成器

    第3章 流程控制.迭代器.生成器 3.1 选择语句 1.语法:(1)if -else (2)if-elif-else 2.注意:(1)每个条件后面要使用冒号:(2)使用缩进划分语句块(3)python ...

  3. pythonfor循环遍历list_为什么for循环可以遍历list:Python中迭代器与生成器

    1 引言 只要你学了Python语言,就不会不知道for循环,也肯定用for循环来遍历一个列表(list),那为什么for循环可以遍历list,而不能遍历int类型对象呢?怎么让一个自定义的对象可遍历 ...

  4. javascript迭代器_JavaScript符号,迭代器,生成器,异步/等待和异步迭代器-全部简单解释...

    javascript迭代器 by rajaraodv 通过rajaraodv JavaScript符号,迭代器,生成器,异步/等待和异步迭代器-全部简单解释 (JavaScript Symbols, ...

  5. 完全理解 Python 迭代对象、迭代器、生成器(转)

    完全理解 Python 迭代对象.迭代器.生成器 本文源自RQ作者的一篇博文,原文是Iterables vs. Iterators vs. Generators » nvie.com,俺写的这篇文章是 ...

  6. 简单介绍python迭代器和生成器

    这篇文章主要介绍了Python中的迭代器和生成器,涉及到Python中很多重要的特性,需要的朋友可以参考下,希望能够给你带来帮助 python迭代器和生成器 1.迭代器 这里用字典示例 while T ...

  7. python迭代器和生成器_python中迭代器和生成器。

    前言:很多python教程中,对python的解释不容易理解,本文记录自己的理解和体会,是对迭代器和生成器的初步理解. 迭代器: 迭代器的实质是实现了next()方法的对象,常见的元组.列表.字典都是 ...

  8. python3可迭代对象、迭代器、生成器、协程yield入门

    #!/usr/bin/env python # -*- coding: utf-8 -*- # @Date : 2019-01-24 16:13:07 # @Author : cdl (1217096 ...

  9. python yield用法_Python中迭代器和生成器的区别?

    公众号新增加了一个栏目,就是每天给大家解答一道Python常见的面试题,反正每天不贪多,一天一题,正好合适,只希望这个面试栏目,给那些正在准备面试的同学,提供一点点帮助! 小猿会从最基础的面试题开始, ...

最新文章

  1. JavaScript两个数组是否有相同元素
  2. linux 软件装到hone,如何在Linux系统安装Apollo
  3. OFBiz + Opentaps 目录管理 十三. 配置产品搜索
  4. 【theano-windows】学习笔记七——logistic回归
  5. 使用SALT-API进入集成开发的简单样例
  6. 技术管理者怎样跳出“泥潭”
  7. 简述List、Set、Map类型的集合的各自特点
  8. mysql 迁移后无法启动_Mysql数据迁移后启动出错_MySQL
  9. AI 开发者如何摆脱只有“人工”没有“智能?
  10. linux卸载wine qq,ubuntu安装wineQQ
  11. 赛默飞世尔Thermo Fisher仪器电路板维修故障概述
  12. 在linux系统中查看mysql版本_Linux系统下查看mysql版本的四种方法_MySQL
  13. 苹果电脑Mac电脑使用心得M1芯片快捷键
  14. 100条历史典故,读懂半个中国
  15. 上dnf一直连接服务器中,Win7系统下玩dnf提示正在连接服务器如何解决
  16. 不需要再手写 onSaveInstanceState 了,因为你的时间非常值钱
  17. 正则校验字符串中汉字数量及总数量
  18. JAVA课程设计(小游戏贪吃蛇)完整源码附素材(二)
  19. 《c语言程序设计》网课答案,合理的服务半径是指居住区内达到居住区级公共服务设施的最大步行距离,一般为 800~1000 m,在地形起伏的地区还应适当减少。...
  20. Ubuntu下将rm命令替换为trash命令

热门文章

  1. vue 路由监听 watch
  2. seleniumbase学习总结6 - 落地常见问题
  3. Mixamo骨骼转为Unreal骨骼方法(1)
  4. 数据科学之 如何找到指标的最 佳分裂点的几个想法
  5. 雷击浪涌设计:保险丝选型
  6. Calendar获取当前季度、月、周的开始时间结束时间
  7. 如何用云服务器进行深度学习
  8. Application Repository一键启用微信告警通知
  9. 黑客大神用什么杀毒? Windows 自带的就够, 只是加了亿点微小的强化
  10. 2019成长复盘2020成长规划