生成器generator

1.引出生成器

  通过列表⽣成式,我们可以直接创建⼀个列表。但是,受到内存限制,列表容量肯定是有限的。⽽且,创建⼀个包含非常多个元素的列表,不仅占⽤很⼤的存储空间,如果我们仅仅需要访问前⾯⼏个元素,那后⾯绝⼤多数元素占⽤的空间都⽩⽩浪费了。

# -*- coding: utf-8 -*-
# @File  : 引出生成器.py
# @author: Flyme awei
# @email : Flymeawei@163.com
# @Time  : 2022/8/20 21:00# 列表生成式
lst = [i for i in range(10)]
print(lst)
print(type(lst))# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# <class 'list'>

  所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?接下来,引出我们的生成器


2.创建生成器

  • 通过列表生成式创建
# -*- coding: utf-8 -*-
# @File  : 创建生成器.py
# @author: Flyme awei
# @email : Flymeawei@163.com
# @Time  : 2022/8/20 20:59g = (i for i in range(10))
print(g)
print(type(g))# <generator object <genexpr> at 0x0000021B19A11D60>
# <class 'generator'>

  这样就不必创建完整的list,从⽽节省⼤量的空间。在Python中,这种⼀边循环⼀边计算的机制,称为⽣成器:generator

  创建列表生成器的区别仅在于最外层的 [ ]( )lst 是⼀个列表,⽽ g 是⼀个⽣成器。我们可以直接打印出 lst 的每⼀个元素,但我们怎么打印出 g 的每⼀个元素呢?如果要⼀个⼀个打印出来,可以通过 next() 函数获得⽣成器的下⼀个返回值:

  • 通过 next() 函数获得⽣成器的下⼀个返回值
# -*- coding: utf-8 -*-
# @File  : 创建生成器.py
# @author: Flyme awei
# @email : Flymeawei@163.com
# @Time  : 2022/8/20 20:59lst = [i for i in range(10)]
g = (i for i in range(10))
print(g)
print(type(g))print(next(g))  # 0
print(next(g))  # 1
print(next(g))  # 2
print(next(g))  # 3
print(next(g))  # 4
print(next(g))  # 5
print(next(g))  # 6
print(next(g))  # 7
print(next(g))  # 8
print(next(g))  # 9
print(next(g))

  ⽣成器保存的是算法,每次调⽤ next(g) ,就计算出 g 的下⼀个元素的值,直到计算到最后⼀个元素,没有更多的 元素时,抛出 StopIteration 的异常。

  当然,这种不断调⽤ next() 实在是太繁琐了,虽然是点一次出现一次,但正 确的⽅法是使⽤ for 循环,因为⽣成器也是可迭代对象。

  • 也可以通过for-in循环打印出来
# -*- coding: utf-8 -*-
# @File  : 创建生成器.py
# @author: Flyme awei
# @email : Flymeawei@163.com
# @Time  : 2022/8/20 20:59g = (i for i in range(10))
print(g)
print(type(g))# print(next(g))  # 0
# print(next(g))  # 1
# print(next(g))  # 2
# print(next(g))  # 3
# print(next(g))  # 4
# print(next(g))  # 5
# print(next(g))  # 6
# print(next(g))  # 7
# print(next(g))  # 8
# print(next(g))  # 9
# print(next(g))for i in g:print(i)

  所以,我们创建了⼀个⽣成器后,基本上永远不会调⽤ next() ,⽽是通过 for 循环来迭代它,并且不需要关心StopIteration 异常。

  generator非常强大。如果推算的算法比较复杂,用类似列表生成式的 for 循环无法实 现的时候,还可以用函数来实现。比如,著名的斐波拉契数列Fibonacci,除第一个和第二个数外,任意一个 数都可由前两个数相加得到:1, 1, 2, 3, 5, 8, 13, 21, 34, ...

  斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:

代码如下

# -*- coding: utf-8 -*-
# @File  : 函数写斐波那契数列.py
# @author: Flyme awei
# @email : Flymeawei@163.com
# @Time  : 2022/8/20 21:14# 定义一个斐波那契函数
def fib(times):# 初始化n = 0a, b = 0, 1while n < times:print(b)a, b = b, a+bn += 1fib(6)

  仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator

  也就是说,上面的函数离generator仅一步之遥。要把 fib 函数变 成generator,只需要把 print(b) 改为 yield(b) 就可以了。

  • 通过yield关键字创建
# -*- coding: utf-8 -*-
# @File  : yield创建生成器.py
# @author: Flyme awei
# @email : Flymeawei@163.com
# @Time  : 2022/8/20 21:17def fib(times):# 初始化n = 0a, b = 0, 1while n < times:yield ba, b = b, a+bn += 1f = fib(6)
print(f)
# <generator object fib at 0x00000197C5E56350>
# f 是一个生成器对象print(next(f))
print(next(f))
print(next(f))
print(next(f))
print(next(f))
print(next(f))

  在上⾯fib的例⼦,我们在循环过程中不断调⽤ yield ,就会不断中断。当然要给循环设置⼀个条件来退出循环,不然就会产⽣⼀个⽆限数列出来。同样的,把函数改成generator后,我们基本上从来不会⽤ next() 来获取下⼀个返 回值,⽽是直接使⽤ for 循环来迭代:

# -*- coding: utf-8 -*-
# @File  : yield创建生成器.py
# @author: Flyme awei
# @email : Flymeawei@163.com
# @Time  : 2022/8/20 21:17def fib(times):# 初始化n = 0a, b = 0, 1while n < times:yield ba, b = b, a+bn += 1f = fib(6)
print(f)
# <generator object fib at 0x00000197C5E56350>
# f 是一个生成器对象for i in f:print(i)


3.遍历生成器的方式

  • 通过next()函数

  • 通过 for- in循环打印

  • objict内置的__next__()方法

  • send() 方法,生成器的第一个值必须是send(None),后面没有限制

# -*- coding: utf-8 -*-
# @File  : 遍历生成器.py
# @author: Flyme awei
# @email : Flymeawei@163.com
# @Time  : 2022/8/20 21:24# 创建一个生成器g
g = (i for i in range(10))print(next(g))  # 0
print(next(g))  # 1print(g.__next__())  # 2
print(g.__next__())  # 3print(g.send(None))  # 4
print(g.send(''))  # 5
print(g.send(1))  # 6for i in g:print(i)
# 7
# 8
# 9

4.生成器总结

  ⽣成器是这样⼀个函数,它记住上⼀次返回时在函数体中的位置。对⽣成器函数的第⼆次(或第 n 次)调⽤跳转⾄该函数中间,⽽上次调⽤的所有局部变量都保持不变。

  ⽣成器不仅记住了它数据状态;⽣成器还记住了它在流控制构造(在命令式编程中,这种构造不只是数据值)中的位置。

生成器的特点:

  • 节约内存

  • 迭代到下⼀次的调⽤时,所使⽤的参数都是第⼀次所保留下的,在整个所有函数调⽤的参数都是第⼀次所调⽤时保留的,⽽不是新创建的。

【Python高级语法】——生成器(generator)相关推荐

  1. Python高级语法系列

    Python高级语法(1)-抽象类 Python高级语法(2)-多继承和MRO继承机制 Python高级语法(3)-global和nolocal关键字使用详解 Python高级语法(4)-魔法函数__ ...

  2. Python程序设计与科学计算精录总结Episode.3 Python高级语法:文件、异常、标准库和问题解决模式知识总结(基于Michael导师Python课程与VS2019)

    今天是2020年5月20日,这个对于博主来说平凡的一天,但社交媒体上早就炸开锅了. 博主认为,有些人受过伤之后,就爱的小心翼翼,迟迟不敢去再次追求自己的另一半,就这样,渐渐的过了能够大胆去爱的年纪,一 ...

  3. Python面试题大全(二):python高级语法

    目录 Python高级 元类 42.Python中类方法.类实例方法.静态方法有何区别? 43.遍历一个object的所有属性,并print每一个属性名? 44.写一个类,并让它尽可能多的支持操作符? ...

  4. Python学习之旅三:python高级语法

    使用pycharm和jupter notebook. 1 包 1.1 模块 一个模块就是一个包含python代码的文件,后缀名为.py即可,模块就是个python文件. 1.1.1 为什么要使用模块呢 ...

  5. Python高级教程-生成器

    生成器(Generator) 通过列表生成式,可以直接创建一个列表.但是,受内存限制,列表的容量肯定是有限的.而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几 ...

  6. python高级语法装饰器_Python高级编程——装饰器Decorator超详细讲解上

    Python高级编程--装饰器Decorator超详细讲解(上篇) 送你小心心记得关注我哦!! 进入正文 全文摘要 装饰器decorator,是python语言的重要特性,我们平时都会遇到,无论是面向 ...

  7. Python高级语法-正则表达式

    正则表达式在字符串匹配中起到巨大的作用. 简介 几个数据提取工具对比: re(正则表达式):速度很快,难度高(语法难记),不需要安装(python标准库内置) bs(BeautifulSoup):速度 ...

  8. 廖雪峰python - 高级特性 - 生成器 _ 练习详解

    杨辉三角:每个数等于它上方两数之和.空位看作0 答案: #定义函数 def triangles():L = [1] // L是只含1的list(列表)yield L // generator的函数遇到 ...

  9. Python高级语法-详解set机制

    集合过滤机制 文章目录 集合过滤机制 简介 Set详解 Set使用 补充说明 简介 底层分析set的实现原理. 详细分析Python的set容器如何过滤自定义类. 代码实现多熟悉自定义类的按照指定属性 ...

最新文章

  1. 红外发送管的角度特性测试
  2. Photo Stack效果
  3. Table options do not contain an option key ‘connector‘ for discovering a connector
  4. Taro+react开发(93):判断是否是H5端
  5. Taro+react开发(31)微信小程序都是要通过编译的
  6. 玩转Android之MVVM开发模式实战,炫酷的DataBinding!
  7. platform_driver_register()--如何match之后调用probe
  8. javascript文本对象
  9. linux ps画图,PhotoGIMP:让Linux下的GIMP交互体验就像Photoshop
  10. QOS边界信任COS-交换机
  11. jQuery 图像裁剪插件Jcrop
  12. struts 1.x 原理
  13. ai 数据模型 下载_为什么需要将AI模型像数据一样对待
  14. (附源码)springboot垃圾自动分类管理系统 毕业设计 160846
  15. 数学基础task08 二重积分
  16. 史玉柱加持,Playtika上市能否圆昔日“巨人”翻身梦?
  17. 1.微信回到首页直接退出网页 2.vue app返回直接退出问题, 首页返回两次退出解决
  18. Nsca安装简单步骤
  19. 虚拟环境位置查找与配置可使用cuda编译器
  20. Java实现字符串反转的几种方法

热门文章

  1. (开源)3D即时战略游戏:Glest 3.12
  2. Mac OS X 重置网卡
  3. The King's Ups and Downs UVALive - 6177
  4. 用css实现聊天对话框向上小三角效果
  5. [乐意黎原创] JS根据useAgent来判断edge, ie, firefox, chrome, opera, safari 等浏览器的类型及版本
  6. 前复权和后复权有什么区别
  7. AE教程:如何在After Effects中创建一个闪烁的眼睛过渡
  8. 你终于下定决心,辞职开始创业,然后…
  9. 【C语言】判断一个数是不是回文数
  10. 720全景展示是什么?全景展示有什么用?