文章目录

  • 一、迭代器
    • 1. 可迭代对象(Iterable)
    • 2. 迭代器对象(Iterator)
    • 3. for 循环原理
    • 4. 迭代器的优缺点
  • 二、生成器
    • 1. yield 原理
    • 2. yield 和 return 区别
    • 3. yield 表达式应用
    • 4. 生成器的优点
  • 结语

一、迭代器

迭代器即用来迭代取值的工具,是一个可以记住遍历的位置的对象。

迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。
迭代器只能往前不能后退

1. 可迭代对象(Iterable)

通过索引的方式进行迭代取值,实现简单,但仅适用于序列类型:字符串,列表,元组。

对于没有索引的字典、集合等非序列类型,必须找到一种不依赖索引来进行迭代取值的方式,这就用到了迭代器。

字符串、列表、元组、字典、集合、打开的文件都是可迭代对象

迭代器对象可以使用常规for语句进行遍历,也可以使用 next() 函数。

2. 迭代器对象(Iterator)

迭代器对象是内置有iter和next方法的对象,打开的文件本身就是一个迭代器对象。

执行迭代器对象 .iter() 方法得到的仍然是迭代器本身

执行迭代器 .next() 方法就会计算出迭代器中的下一个值

3. for 循环原理

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

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

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

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

for 循环在工作时:

首先会调用可迭代对象goods内置的iter方法拿到一个迭代器对象,

然后再调用该迭代器对象的next方法将取到的值赋给item,执行循环体完成一次循环,

周而复始,直到捕捉StopIteration(停止迭代),结束迭代。

4. 迭代器的优缺点

优点

1、为序列和非序列类型提供了一种统一的迭代取值方式

2、惰性计算:迭代器对象表示的是一个数据流,可以只在需要时才去调用next来计算出一个值。

迭代器同一时刻在内存中只有一个值,因而可以存放无限大的数据流。

而对于其他容器类型,如列表,需要把所有的元素都存放于内存中,受内存大小的限制,可以存放的值的个数是有限的。

缺点

1、除非取尽,否则无法获取迭代器的长度。

2、只能取下一个值,不能回到开始

迭代器产生后的唯一目标就是重复执行next方法直到值取尽,否则就会停留在某个位置,等待下一次调用next。

若是要再次迭代同个对象,只能重新调用iter方法创建一个新的迭代器对象。

如果有两个或者多个循环使用同一个迭代器,必然只会有一个循环能取到值。

二、生成器

使用了 yield 的函数被称为生成器(generator)。

生成器是一个返回迭代器的函数,只能用于迭代操作,可理解为生成器就是一个自定义迭代器

1. yield 原理

yield 能够临时挂起当前函数,记下其上下文(包括局部变量、待决的 try catch 等),将控制权返回给函数调用者。

当下一次再调用其所在生成器时,会恢复保存的上下文,继续执行剩下的语句,直到再遇到 yield 或者退出为止

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

2. yield 和 return 区别

yield可以用于返回值,但不同于return。

函数一旦遇到return就结束了,销毁上下文(弹出栈帧),将控制权返回给调用者。

yield可以保存函数的运行状态,挂起函数,用来返回多次值。

因此,以 yield 进行执行流控制的函数称为生成器函数,以 return 进行执行流控制的函数就是普通函数。

由于可以临时挂起函数的执行,yield 可以充当其调用者和被挂起函数间交互的桥梁。

3. yield 表达式应用

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

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

可以拿到函数的生成器对象持续为函数体send值,如下

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

针对表达式形式的yield,生成器对象必须事先被初始化一次

让函数挂起在food=yield的位置,等待调用g.send()方法为函数体传值。

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('蒸鹿尾儿')
['蒸羊羔', '蒸熊掌', '蒸鹿尾儿']

4. 生成器的优点

  1. 精简代码

使用 yield 关键字或者生成器表达式可以很方便的生成一个迭代器对象。

为了说明这一点,我们来比较一下对于一个需求的不同实现。

该需求很简单:获取前 n 个自然数。

1、构造一个数组然后返回。当 n 很小的时候,该实现没有什么问题,但是当 n 变得很大,内存是吃不消的。

2、用生成器模式,不用 yield。构造一个对象,并实现__iter__ 和 __next__方法。但为了实现一个简单的需求却不得不构造冗长的代码。

3、使用了 yield 构造一个生成器函数

# 产生项目而不是返回列表的生成器
def firstn(n):num = 0while num < n:yield numnum += 1sum_of_first_n = sum(firstn(1000000))
  1. 提高性能

这一条主要是针对内存使用上来说的。

因为迭代器不会保存所有值,而是在运行中动态的计算出数列的各个值,并将之前的数值扔掉。

这里举个实例。

假设我们有一个很大的文件(比如说 16G ) ,但是你的电脑只有 8G 内存,你如何利用 Python 对其进行处理?

答案是使用 yield 构造生成器。

def read_by_chunks(file, chunk_size=1024):while True:data = file.read(chunk_size)if not data:breakyield dataf = open('your_big_file.dat')
for chunk in read_by_chunks(f):process_chunk(chunk)

这种通过构造生成器逐块读取的方法叫做惰性加载,也叫流式读取,是处理大文件的一种常见方式。

惰性加载也被运用在软件设计和网页设计当中,其特征为用户通过鼠标,滚动浏览页面,直到页面下方时,就会自动加载更多内容。

如果你的是文本文件,可以按行读取,那代码就更简单了:

with open('your_big_file.txt') as f:for line in f: process_line(line)

Python文件句柄(file handle)就是一个迭代器,默认会将文件按行分割以惰性加载。

结语

以上这些,就是Python迭代器与生成器的基础知识,希望对大家有所帮助。 如果大家有任何疑问请给我留言,我会尽快回复大家。在此也非常感谢大家对CSDN的支持!

Python迭代器和生成器详解(包括yield详解)相关推荐

  1. python迭代器与生成器实际用途_python迭代器和生成器

    python迭代器和生成器 一.迭代器 1.什么是迭代器 说迭代器之前有个相关的名词需要介绍: 可迭代对象:只要定义了iter()方法,我们就说该对象是可迭代对象,并且可迭代对象能提供迭代器. 在Py ...

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

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

  3. python生成器 图片分类_python批量处理图片图片Python迭代器和生成器介绍

    Python迭代器和生成器介绍迭代器 迭代器是一个实现了迭代器协议的对象,Python中的迭代器协议就是有next方法的对象会前进到下一结果,而在一系列结果的末尾是,则会引发StopIteration ...

  4. python迭代器与生成器答案_史上最全 Python 迭代器与生成器

    原标题:史上最全 Python 迭代器与生成器 作者:浪子燕青 链接:http://www.langzi.fun/迭代器与生成器.html 迭代器与可迭代对象 概念 迭代器:是访问数据集合内元素的一种 ...

  5. 五分钟学会python函数_五分钟带你搞懂python 迭代器与生成器

    前言 大家周末好,今天给大家带来的是Python当中生成器和迭代器的使用. 我当初第一次学到迭代器和生成器的时候,并没有太在意,只是觉得这是一种新的获取数据的方法.对于获取数据的方法而言,我们会一种就 ...

  6. 全面理解Python迭代器和生成器

    | 在Python中,很多对象都是可以通过for语句来直接遍历的,例如list.string.dict等等,这些对象都可以被称为可迭代对象.至于说哪些对象是可以被迭代访问的,就要了解一下迭代器相关的知 ...

  7. python 列表生成器放while_史上最全 Python 迭代器与生成器

    原标题:史上最全 Python 迭代器与生成器 转自:浪子燕青 http://www.langzi.fun/迭代器与生成器.html 概念 迭代器:是访问数据集合内元素的一种方式,一般用来遍历数据,但 ...

  8. python迭代器与生成器_python的迭代器与生成器实例详解

    本文以实例详解了python的迭代器与生成器,具体如下所示: 1. 迭代器概述: 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后 ...

  9. python 迭代器、生成器、yield、iter

    文章目录 1. 迭代器 2. 生成器 3. 标准库 3.1 过滤 3.2 映射 3.3 合并 3.4 排列组合 3.5 重新排列 4. yield from 5. 可迭代的归约函数 6. iter 还 ...

最新文章

  1. oracle之 安装 11G RAC 报 NTP failed
  2. WPF – 使用触发器
  3. Incorrect line ending: found carriage return (\r) without corresponding newline (\n)错误的解决方案...
  4. 论文浅尝 | 用图网络做小样本学习
  5. Windows运行命令收集
  6. python处理带有‘\x‘的字符串,拆分,解码,重组
  7. SpringCloud项目总结
  8. 更灵活的定位内存地址的方法02 - 零基础入门学习汇编语言33
  9. Atitit 财政支出减少之道---------蹭银行与金融机构的补贴之道
  10. 2-SAT 及 一点习题
  11. [JLOI2009]二叉树问题
  12. 按键精灵在帖吧的引流代码
  13. ASP.Net中控件的EnableViewState属性
  14. https://blog.csdn.net/zxp_cpinfo/article/details/53692922
  15. Android Studio快速开发之道
  16. Andriod8.0去除Launcher谷歌搜索框
  17. 计算机应用基础——计算机软件(二)
  18. 令人头痛的WH_CBT钩子,使窗口前置——泪水+汗水的赞歌
  19. [Oracle] 一个通过添加本地分区索引提高SQL性能的案例
  20. ubuntu 下的pdfcrop功能不(pdf剪切)

热门文章

  1. 旅行青蛙服务器维护时间,旅行青蛙小青蛙多久出门一次?要什么时候才会出门...
  2. 14.0高等数学五- 函数的幂级数展开(泰勒级数或者麦克劳林级数)
  3. 温莎大学的计算机专业,加拿大留学,温莎大学英语计算机专业了解一下
  4. python 删除pdf页面_使用Python批量删除扫描PDF中的空白页
  5. vue省市区 下拉框实现
  6. 谷歌浏览器提示“喔唷,崩溃啦!”
  7. 计算机网络波动大,网络不稳定怎么办,小编教你电脑网络不稳定怎么办
  8. 酒店:二维码如何应用于酒店管理
  9. 不同域名间的session共享
  10. cisco VoIP软电话配置实验