创建生成器

  创建生成器需要两部步骤

  1. 定义一个包含yield语句的函数
  2. 调用第一步创建的函数得到生成器
def test(val,step):
2 print("函数开始执行")
3 cur = 0
4 for i in range(val):
5 cur += i * step
6 yield cur
7

yeild cur 语句的两个作用:

  1. 每次返回一个值,有点类似与return语句
  2. 冻结执行,程序每次执行到yield语句时就会停止运行

在程序被冻结时,当程序调用next()函数获取生成器的下一个值时,程序才会继续向下执行

需要注意的是,当程序调用含yeild的函数时,并不会立即执行,它只是返回一个生成器。

if __name__ == "__main__":
9 #此时程序并不会立即运行
10 t = test(10,2)
11 #获取生成器的第一个值
12 print(next(t))#生成器被冻结在yield处
13 print(next(t))

运行结果:

函数开始执行
0
2
从运行结果可以看出,当程序执行 t = test(10,2)时,程序并没有开始执行test()函数,当程序第一次调用next(t)时,test()函数才开始执行。当程序调用next(t)时,生成器会返回yield cur 语句返回的值,程序被冻结在yield语句处,所以可以看到生成器第一次输出的值是0

当程序第二次调用next(t),程序的“冻结”被解除,继续向下执行。

程序可以用for循环来遍历生成器,相当于不断的使用next()函数来获取生成器的值。

for ele in t:
print(ele,end = "\t")

程序运行结果

6       12      20      30      42      56      72      90
由于前面两次调用next()已经获取了生成器的前两个值,所以循环第一次输出的值为6

程序也可以使用list()或者tuple()将生成器能生成的值转换成列表或者元组

 17     t1 = list(test(10,1))
18 print(t1)
19 t2 = tuple(test(10,1))
20 print(t2)

程序运行结果

函数开始执行
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
函数开始执行
(0, 1, 3, 6, 10, 15, 21, 28, 36, 45)
python主要提供两种方法来创建生成器

  1. 使用for循环的生成器推导式
  2. 调用带yield语句的生成器函数

生成器是python的一个特色功能,在其他语言中往往没有对应的机制,生成器具有以下优势

  1. 当使用生成器来生成多个数据时,程序是按需获取数据的,它不会一开始酒吧所有数据都生成出来,而是next()获取下一个数据时,生成器才会执行一次,因此可以减少代码的执行次数。
  2. 当函数需要返回多个数据时,如果不使用生成器,程序就会使用列表或元组来收集函数返回的多个值,当函数要返回的数据亮比较大时,这些列表和元组会带来一定的内存开销。
  3. 使用生成器会使代码跟家简洁。

生成器的方法

当生成器运行起来后,开发者还可以为生成器提供值,通过这种方法让生成器与外部程序进行动态的数据交换

  1. 外部程序通过send()方法发送数据
  2. 生成器函数使用yield语句接收数据

只有等到程序被冻结之后,外部程序才能使用send()方法向生成器发送数据。获取生成器第一次生成的值,应该使用next()函数。如果程序非要用send()来获取生成器第一次生成的值,则不能向生成器发送数据,只能传入None参数。

  7 def square(val):
8 i = 0
9 out_val = None
10 while True:
11 #使用yield语句生成值,使用out_val来接受send()发送的
参数值
12 out_val = (yield out_val ** 2) if out_val is not No ne else (yield i ** 2)
13 #如果程序使用send()方法获取生成器的下一个值,out_va l会获取send()方法的参数值
14 if out_val is not None:
15 print("%d" % out_val)
16 i += 1

运行结果

0
1
9
81
9

上面程序第一次使用send()方法来获取生成器的下一个值,只能传入None参数。当程序冻结时,并没有给out_val进行赋值,根据运行结果可以看出第一次生成器的值为0。接下来调用next()函数获取生成器的下一个值,程序从冻结处(对out_val进行赋值)向下执行,out_val被赋值为None,所以程序执行yield i ** 2,生成器返回的结果为1,程序再次被冻结。

接下来程序调用send(9),程序从冻结处向下运行(给out_val进行赋值),此时out_val被赋值为9,生成器返回值为81

接下来程序调用next(),out_val被赋值为None,此时程序执行yield i ** 2,此时i的值已经递增为3,生成器返回的值为9

Python-生成器的更多相关文章

  1. python——生成器

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

  2. Python生成器-博文读后感

    Windows 10家庭中文版,Python 3.6.4, 上午看过了一篇讲Python生成器的博文: 提高你的Python: 解释‘yield’和‘Generators(生成器)’(英文原文) 这篇 ...

  3. 小学生都能学会的python(生成器)

    小学生都能学会的python(生成器) 1. 生成器 生成器的本质就是迭代器. 生成器由生成器函数来创建或者通过生成器表达式来创建 # def func(): # lst = [] # for i i ...

  4. Python 生成器 (generator) & 迭代器 (iterator)

    python 生成器 & 迭代器 生成器 (generator) 列表生成式 列表生成式用来生成一个列表,虽然写的是表达式,但是储存的是计算出来的结果,因此生成的列表受到内存大小的限制 示例: ...

  5. python生成器学习

    python生成器学习: 案例分析一: def demo(): for i in range(4): yield i g=demo() g1=(i for i in g) #(i for i in d ...

  6. 【python之路29】python生成器generator与迭代器

    一.python生成器 python生成器原理: 只要函数中存在yield,则函数就变为生成器函数 #!usr/bin/env python # -*- coding:utf-8 -*- def xr ...

  7. Generator - Python 生成器

    Generator, python 生成器, 先熟悉一下儿相关定义, generator function 生成器函数, 生成器函数是一个在定义体中存有 'yield' 关键字的函数. 当生成器函数被 ...

  8. python生成器原理剖析

    python生成器原理剖析 函数的调用满足"后进先出"的原则,也就是说,最后被调用的函数应该第一个返回,函数的递归调用就是一个经典的例子.显然,内存中以"后进先出&quo ...

  9. 什么是Python生成器?与迭代器的关系是什么?

    生成器是一个特殊的迭代器,它保存的是算法,每次调用next()或send()就计算出下一个元素的值,直到计算出最后一个元素,没有更多的元素时,抛出StopIteration.生成器有两种类型,一种是生 ...

  10. Python 生成器与迭代器 yield 案例分析

    前几天刚开始看 Python ,后因为项目突然到来,导致Python的学习搁置了几天.然后今天看回Python 发现 Yield 这个忽然想不起是干嘛用的了(所以,好记性不如烂笔头.).然后只能 花点 ...

随机推荐

  1. PAT L2-016. 愿天下有情人都是失散多年的兄妹 (BFS)

    L2-016. 愿天下有情人都是失散多年的兄妹 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 呵呵.大家都知道五服以内不得通婚 ...

  2. HDU 3966 Aragorn's Story(树链剖分)题解

    题意:给一棵树,要求你对一个路径上的值进行加减,查询某个点的值 思路:重链剖分. 由于分了轻重儿子,我每次到重儿子的top只要O(1),经过的轻儿子最多logn条,那么我每次往上跳最多跳logn次. ...

  3. 013.NET5_MVC_Razor扩展Html控件01

    Razor扩展控件  第一种方式: 1. 定义一个静态类 2. 定义静态扩展方法,扩展IHtmlHelper类型,返回IHtmlContent类型: 本质:通过后台方法,返回一个已经存在的Html标签 ...

  4. 最新 Vue 源码学习笔记

    最新 Vue 源码学习笔记 v2.x.x & v3.x.x 框架架构 核心算法 设计模式 编码风格 项目结构 为什么出现 解决了什么问题 有哪些应用场景 v2.x.x & v3.x.x ...

  5. MathJax TeX & LaTeX

    MathJax TeX & LaTeX mathcal https://leetcode-cn.com/problems/binary-search/solution/er-fen-cha-z ...

  6. js 小数转整数,避免精度损失 bug

    js 小数转整数,避免精度损失 bug const arr = [ 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ]; // ( ...

  7. Parcel all in one

    Parcel all in one Parcel https://parceljs.org/ # cli $ yarn global add parcel-bundler $ npm install ...

  8. 【C#】反射的用法及效率对比

    反射实例化类 public class Person { public string Name { get; set; } public Person(string name) { this.Name ...

  9. django学习-8.django模板继承(block和extends)

    1.前言 django模板继承的作用:模板可以用继承的方式来实现复用,减少冗余内容. 一般来说,一个网站里一般存在多个网页的头部和尾部内容都是一致的,我们就可以通过模板继承来实现复用. 父模板用于放置 ...

  10. 数据处理_HIVE增量ETL的一种方式

    适用场景: 贴源层主表历史数据过大,ETL不涉及历史数据对比或聚合 处理流程: 1.确定一个业务主键字段或物理主键字段 2.确定一个可以判断增量数据范围的字段,这取决于具体的业务场景,一般选用记录的创 ...