自学Python4.7-生成器(方式一:生成器函数)
自学Python之路-Python基础+模块+面向对象
自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django
自学Python4.7 - 生成器(方式一:生成器函数)
定义:生成器(generator)是一个包含yield关键字的函数,当它被调用的时候,在函数体中的代码不会被执行,而是会返回一个迭代器。
(一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator);
如果函数中包含yield语法,那这个函数就会变成生成器;)
- 生成器是一个特殊的程序,可以被用作控制循环的迭代行为
- 生成器类似于返回值为数组的一个函数,这个函数可以接收参数,可以被调用,但是,不同于一般的函数会一次性返回包含了所有数值的数组,生成器一次 只产生一个值,这样消耗的内粗数量大大减少,而且允许调用函数可以很快的开始处理前几个返回值。因此,生成器看起来像一个函数但是表现的却像一个迭代器
python提供了两种基本的生成器方式:
- 生成器函数:也是用def来定义,利用关键字yield一次返回一个结果,阻塞,重新开始
每次请求一个值,就会执行生成器中的代码,知道遇到一个yield或者return语句
①yield语句意味着应该生成一个值
②return语句意味着要停止执行(不生成任何东西,只有在一个生成器中使用时才能进行无参数调用) - 生成器表达式:返回一个对象,这个对象只有在需要的时候才产生结果
1. 生成器函数:
为什么叫生成器函数?因为他随着时间的推移生成了一个数值队列。一般的函数在执行完毕之后会返回一个值然后退出,但是生成器函数会自动挂起,然后重新拾起继续执行,他会利用yield关键字关起函数,给调用者返回一个值,同时保留了当前的足够多的状态,可以使函数继续执行。
生成器和迭代协议是密切相关的,可迭代的对象都有一个__next()__成员方法,这个方法要么返回迭代的下一项,要么引起异常结束迭代。
为了支持迭代协议,拥有yield语句的函数被编译为生成器,这类函数被调用时返回一个生成器对象,返回的对象支持迭代接口,即成员方法__next()__继续从中断处执行执行。
def func(): #func是函数称为生成器,当执行此函数func()时会得到一个迭代器。
yield 1
yield 2
yield 3
yield 4
temp = func()
print(temp.__next__())
print(temp.__next__())
print(temp.__next__())
print(temp.__next__())

def creat_counter(n):
print('create counter')
while True:
yield n
print('increment n')
n += 1
cnt = creat_counter(2)
print(cnt)
print(next(cnt))
print(next(cnt))
print(next(cnt))

分析以上的列子:
- 在create_counter函数中出现了关键字yield,预示着这个函数每次只产生一个结果值,这个函数返回一个生成器(通过第一行输出可以看出来),用来产生连续的n值
- 在创造生成器实例的时候,只需要像普通函数一样调用就可以,但是这个调用却不会执行这个函数,这个可以通过输出看出来
- next()函数将生成器对象作为自己的参数,在第一次调用的时候,他执行了create_counter()函数到yield语句,返回产生的值2
- 我们重复的调用next()函数,每次他都会从上次被挂起的地方开始执行,直到再次遇到了yield关键字
def cube(n):
for i in range(n):
yield i ** 3
for i in cube(5):
print(i)

从理解函数的角度出发我们可以将yield类比为return,但是功能确实完全不同,在for循环中,会自动遵循迭代规则,每次调用next()函数,所以上面的结果不难理解。
举例1:

举例2:

举例3: 取不到值会报错

举例4: 使用for循环取值

举例5.1 : 打印出10个哇哈哈

举例5.2 :如果现在有10个哇哈哈, 我现在只想用5个

迭代器依旧延续向下走:

举例6:
def generator():
print('123')
content = yield 1
print('=========',content)
print(456)
yield 2
g = generator()
ret = g.__next__()
print("******",ret)
ret = g.send("hello")
print("**********",ret)

send 获取下一个值的效果和next基本一致,只是在获取下一个值得时候,给上一个yield的位置传递一个数据
使用send的注意事项:
- 第一次使用生成器的时候,是用next获取下一个值
- 函数最后一个yield不能接受外部的值
举例7.1:
获取移动平均值:
10 20 30 10
15 20 17.5

def average():
sum = 0
count = 0
avg = 0
while True:
num = yield avg
sum += num
count += 1
avg = sum/count avg_g = average()
avg_g.__next__()
avg1 = avg_g.send(10)
avg1 = avg_g.send(20)
avg1 = avg_g.send(30)
print(avg1)

举例7.2: 预激生成器的装饰器完成获取移动平均值
def init(func): #装饰器
def inner(*args,**kwargs):
g = func(*args,**kwargs) #g = average()
g.__next__()
return g
return inner @init
def average():
sum = 0
count = 0
avg = 0
while True:
num = yield avg
sum += num # 10
count += 1 # 1
avg = sum/count avg_g = average() #===> inner
ret = avg_g.send(10)
print(ret)
ret = avg_g.send(20)
print(ret)
以上程序执行步骤:


举例8 :
在python3里面的新功能 yield from


.
自学Python4.7-生成器(方式一:生成器函数)的更多相关文章
- 自学Python4.8-生成器(方式二:生成器表达式)
自学Python之路-Python基础+模块+面向对象自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django 自学Pyth ...
- 自学Python4.2 迭代器、生成器
迭代器.生成器一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么, 因为人们很少在迭代途中往后退.另外 ...
- python迭代器和生成器(3元运算,列表生成式,生成器表达式,生成器函数)
1.1迭代器 什么是迭代器: 迭代器是一个可以记住遍历的位置对象 迭代器对象从集合的第一个元素元素开始访问,直到所有元素被访问完结束,迭代器只能往前不会后退. 迭代器有两个基本方法:iter ,nex ...
- python 全栈开发,Day14(列表推导式,生成器表达式,内置函数)
一.列表生成式 生成1-100的列表 li = [] for i in range(1,101): li.append(i) print(li) 执行输出: [1,2,3...] 生成python1期 ...
- Python装饰器、生成器、内置函数、json
这周学习了装饰器和生成器,写下博客,记录一下装饰器和生成器相关的内容. 一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如 ...
- python基础----迭代器、生成器、协程函数及应用(面向过程实例)
一.什么是迭代器协议 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退) 2.可迭代 ...
- python基础--迭代器、生成器、内置函数、面向对象编程
迭代器:迭代器对象从集合的第一个元素开始访问,直到所有的元素都被访问完结束.迭代器只能往前不会后退 迭代:更新换代(重复)的过程,每次的迭代都必须基于上一次的结果 迭代器:迭代取值的工具 使用迭代器的 ...
- 函数与函数式编程(生成器 && 列表解析 && map函数 && filter函数)-(四)
在学习python的过程中,无意中看到了函数式编程.在了解的过程中,明白了函数与函数式的区别,函数式编程的几种方式. 函数定义:函数是逻辑结构化和过程化的一种编程方法. 过程定义:过程就是简单特殊没有 ...
- 测开之数据类型· 第3篇《列表推导式、字典推导式、2种方式创建生成器》
坚持原创输出,点击蓝字关注我吧 作者:清菡 博客:oschina.云+社区.知乎等各大平台都有. 目录 一.列表推导式 二.字典推导式 三.2种方式创建生成器 1.生成器表达式 2.函数里面,通过 y ...
随机推荐
- 每周分享之cookie详解
本章从JS方向讲解cookie的使用.(实质上后端代码也是差不多用法,无非读取和设置两块) 基本用法:document.cookie="username=pengpeng"; 修改 ...
- WebPack牛刀小试
现在页面的功能和需求越来越复杂,繁复杂乱的JavaScript代码和一大堆的依赖包都需要包含在前端页面中.如果还用手动处理就有点像在现代战场上使用小米加步枪的味道了. 为了减小开发的复杂度,前端社区涌 ...
- Python_函数的初识、函数的返回值、函数的参数
1.函数的初识 def关键字 空格 函数名(与变量名命名规则相同):英文冒号 函数体 执行函数:函数名+() 函数是以功能为导向的. def login(): pass def register(): ...
- 福州大学软件工程1816 | W班 团队Alpha阶段成绩汇总排名(第9、10次作业)
写在前面 汇总成绩排名链接 1.作业链接 第九次作业--项目Alpha冲刺(团队) 第十次作业--事后诸葛亮(团队) 2.评分准则 本次作业包括现场Alpha答辩评分(映射总分为100分)+博客分(总 ...
- 如何使用 Docker 来限制 CPU、内存和 IO等资源?
如何使用 Docker 来限制 CPU.内存和 IO等资源?http://www.sohu.com/a/165506573_609513
- Failure to transfer org.apache.maven:maven-archiver:pom:2.5 from https://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval o
pom.xml报错: Failure to transfer org.apache.maven:maven-archiver:pom:2.5 from https://repo.maven.apach ...
- IdentityServer4【QuickStart】之使用ClientCredentials流程保护API
使用ClientCredentials流程保护API 这个示例展示了使用IdentityServer中保护APIs的最基本的场景. 在这个场景中我们会定义一个API和一个想要访问它的客户端.客户端会在 ...
- Linux下面将windows写的脚本转换成 Linux 格式的文件
1.接着上一篇blog 发现有一个问题 vim 打开文件 发现最下面有一行信息: 2. 里面有一些 不一样的地方. linux里面没法执行 ,如果想执行的话 可以输入命令 :set fileforma ...
- Spring Boot+Jsp启动异常
No Java compiler available for configuration options compilerClassName 加入maven配置 <dependency> ...
- python学习笔记(10)--组合数据类型(字典类型)
理解映射: 映射是一种键(索引)和值(数据)的对应.字典是键值对的集合,键值之间无序.用大括号表示{},和dict()创建,键值对用冒号:表示. {键:值,键:值,键:值} >>> ...