020.Python生成器和生成器函数
一 生成器
1.1 基本概念
元组推导式是是生成器(generator)
生成器定义
- 生成器可以实现自定义,迭代器是系统内置的,不能够更改
- 生成器的本质就是迭代器,只不过可以自定义.
生成器有两种定义的方式:
- 生成器表达式 (里面是推导式,外面用圆括号)
- 生成器函数
1.2 元组推导式的形式来写生成器
gen = (i * 2 for i in range(5))
print(gen)
from collections import Iterator
print(isinstance(gen,Iterator))
执行
[root@node10 python]# python3 test.py
<generator object <genexpr> at 0x7fb5ec2e6200>
True
1.3 使用for调用生成器
gen = (i * 2 for i in range(5))
print(gen)
from collections import Iterator
print(isinstance(gen,Iterator))
for i in gen:
print (i)
执行
[root@node10 python]# python3 test.py
<generator object <genexpr> at 0x7fd817c1f200>
True
0
2
4
6
8
1.4 用next进行调用生成器
gen = (i * 2 for i in range(5))
print(gen)
from collections import Iterator
print(isinstance(gen,Iterator))
for i in gen:
print (i)
gen = (i * 2 for i in range(5))
res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen)
print(res)
执行
[root@node10 python]# python3 test.py
<generator object <genexpr> at 0x7f0b564d0200>
True
0
2
4
6
8
0
2
4
6
8
越界错误
gen = (i * 2 for i in range(5))
print(gen)
from collections import Iterator
print(isinstance(gen,Iterator))
for i in gen:
print (i)
gen = (i * 2 for i in range(5))
res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen)
print(res)
#在添加一个会出现越界错误
res = next(gen)
print(res)
执行
1.5 利用for 和next 配合使用 调用生成器
gen = (i * 2 for i in range(5))
print(gen)
from collections import Iterator
print(isinstance(gen,Iterator))
gen = (i * 2 for i in range(5))
for i in range(3):
res = next(gen)
print(res)
执行
[root@node10 python]# python3 test.py
<generator object <genexpr> at 0x7f5e78ef1200>
True
0
2
4
二 生成器函数
2.1 yield 生成器函数
yield 类似于 return
共同点在于:执行到这句话都会把值返回出去
不同点在于:yield每次返回时,会记住上次离开时执行的位置 , 下次在调用生成器 , 会从上次执行的位置往下走
而return直接终止函数,每次重头调用.
yield 6 和 yield(6) 2种写法都可以 yield 6 更像 return 6 的写法 推荐使用
定义一个生成器
def func():
print("one")
yield 1 print("two")
yield 2 print("three")
yield 3 # 初始化生成器函数 => 返回一个生成器对象 简称生成器
gen = func() res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen)
print(res)
执行
[root@node10 python]# python3 test.py
one
1
two
2
three
3
执行过程
首先初始化生成器函数 返回生成器对象,简称生成器
有了生成器之后 可以使用next进行依次的调用
第一次 print(one) 记录当前的状态,暂停等待下一次调用 通过yield 1 返回1 ,阻塞代码
第二次 print(two) 记录当前的状态,暂停等待下一次调用 通过yield 2 返回2 ,阻塞代码
第三次 print(three) 记录当前的状态,暂停等待下一次调用 通过yield 3 返回3 ,阻塞代码
到此已经没有值可以在拿出来了,如果在调用,直接越界报错.
优化生成器
def func():
for i in range(1,101):
yield "我的球衣号码是%d" % (i) # 初始化生成器函数 => 返回一个生成器对象
gen = func() for i in range(30):
res = next(gen)
print(res) for i in range(50):
res = next(gen)
print(res)
2.2 send生成器函数
把值发送给上一个yield 进行接收
next和send区别:
- next 只能取值
- send 不但能取值,还能发送值
send注意点:
- 第一个 send 不能给 yield 传值 默认只能写None (语法的硬性要求)
- 最后一个yield 接受不到send的发送值
def func():
print("start")
res = yield 1
print(res) res = yield 2
print(res) res = yield 3 print(res)
print("end")
#初始化生成器函数,生成生成器
gen = func()
# 生成器.send 第一次发送的时候必须参数是None 硬性语法
res = gen.send(None) #这里相当于res = next(gen)
print(res)
执行
[root@node10 python]# python3 test.py
start
1
第二次可以自定义要发送的值
def func():
print("start")
res = yield 1
print(res) res = yield 2
print(res) res = yield 3 print(res)
print("end")
gen = func()
# 生成器.send 第一次发送的时候必须参数是None 硬性语法
res = gen.send(None)
print(res)
res = gen.send("111")
print(res) res = gen.send("222")
print(res)
执行
[root@node10 python]# python3 test.py
start
1
111
2
222
3
如果没有yield了 , 就没有返回值给你, 在调用直接报错
如果就像在最后一次调用的时候执行剩下的没跑完的代码,使用try..except..来进行异常处理
def func():
print("start")
res = yield 1
print(res) res = yield 2
print(res) res = yield 3 print(res)
print("end")
gen = func()
# 生成器.send 第一次发送的时候必须参数是None 硬性语法
res = gen.send(None)
print(res)
res = gen.send("111")
print(res) res = gen.send("222")
print(res) res = gen.send("222")
print(res)
执行
[root@node10 python]# python3 test.py
start
1
111
2
222
3
222
end
Traceback (most recent call last):
File "test.py", line 25, in <module>
res = gen.send("222")
StopIteration
执行过程
发送的时候 是先发送 ,后接受 #第一次发送的时候必须参数是None 硬性语法
print(start) 记录当前状态, 把yield 1这个值返回取出 , 暂定阻塞,等待下一次调用.
# 第二次调用时,可以自定义要发送的值 被yield 1 这一行收走了,res接收到send发送过去的值为111
那么从这一行继续向下执行
print(res) 111
res = yield 2
把2 返回给res = gen.send(111) 这一行 res 接收到2 print(res) #第三次调用时,发送自定义值222,被res = yield 2接收到 print(res) => 222
然后执行res = yield 3 记录当前状态,把yield 3 这个值返回取出, 代码暂停阻塞,等待下一次调用.
2.3 yield from 函数
- 将一个可迭代对象变成一个迭代器返回
def func():
listvar = [1,2,3,4,4,5]
# yield listvar
yield from listvar # 初始化生成器函数 返回生成器对象 简称生成器
gen = func()
res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen)
print(res)
print("<=for=>")
for i in gen:
print(i)
执行
[root@node10 python]# python3 test.py
1
2
3
4
<=for=>
4
5
020.Python生成器和生成器函数的更多相关文章
- python迭代器和生成器(3元运算,列表生成式,生成器表达式,生成器函数)
1.1迭代器 什么是迭代器: 迭代器是一个可以记住遍历的位置对象 迭代器对象从集合的第一个元素元素开始访问,直到所有元素被访问完结束,迭代器只能往前不会后退. 迭代器有两个基本方法:iter ,nex ...
- python中的生成器函数是如何工作的?
以下内容基于python3.4 1. python中的普通函数是怎么运行的? 当一个python函数在执行时,它会在相应的python栈帧上运行,栈帧表示程序运行时函数调用栈中的某一帧.想要获得某个函 ...
- python学习 day11 (3月16日)----(生成器内置函数)
1生成器 1生成器的本质 一定是迭代器(反之不一定(用send(生成器特有方法)验证))2生成器是可以让程序员自己定义的一个迭代器3生成器的好处,节省内存空间4生成器的特性,一次性的,惰性机制,从上往 ...
- 【学习笔记】--- 老男孩学Python,day13 生成器,生成器函数,各种推倒式和生成器表达式
1. 生成器和生成器函数 生成器的本质就是迭代器 生成器的三种创建办法: 1.通过生成器函数 2.通过生成器表达式创建生成器 3.通过数据转换 2. 生成器函数: 函数中包含了yield的就是生成 ...
- Python进阶(四)----生成器、列表推导式、生成器推导式、匿名函数和内置函数
Python进阶(四)----生成器.列表推导式.生成器推导式.匿名函数和内置函数 一丶生成器 本质: 就是迭代器 生成器产生的方式: 1.生成器函数
- Python入门篇-生成器函数
Python入门篇-生成器函数 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.生成器概述 1>.生成器generator 生成器指的是生成器对象,可以由生成器表达式得到, ...
- python之序列去重以及生成器、生成器函数、生成器表达式与迭代器浅谈
首先要明确序列值类型是否可哈希,因为可哈希的值很简单就可以用 in /not in 写个生成器去判断,如果是不可哈希的就要去转换为可哈希的再用 in/not in 去判断 原地不可变类型(可哈希): ...
- python之迭代器 生成器 枚举 常用内置函数 递归
迭代器 迭代器对象:有__next__()方法的对象是迭代器对象,迭代器对象依赖__next__()方法进行依次取值 with open('text.txt','rb',) as f: res = f ...
- Python第六章-函数05-迭代器&生成器
python作为一个既面向对象,又支持函数式编程的语言,函数的使用方面有很多特点. 比如:闭包,装饰器,迭代器等 函数的高级应用 容器:生活中常见的容器有哪些?袋子,盆子,水杯,书包,铅笔盒... 容 ...
随机推荐
- 批处理文件设置IP以及DNS
先附上批处理文件代码(批处理文件怎么创建自己另行百度,这里不再赘述) Echo offecho ==============请输入序号修改办公区===========echo *********1.家 ...
- Nodejs入门(二)
Nodejs基础api 1.path path模块提供了很多实用的工具函数,用于处理文件与目录的路径,下面是它的api: normalize 方法可以输出规范格式的path字符串 join 方法用于拼 ...
- 敏捷史话(十五):我发明了敏捷估算扑克牌 —— James Greening
雪鸟会议 雪鸟会议前夕,James Grenning 在 Object Mentor 与 Robert C. Martin 一同工作,彼时组织雪鸟会议的 Bob 大叔盛情邀请 James,告知他会议的 ...
- 善用k8s explain
使用kubectl explain来快速了解用法 例如 kubectl explain deployment.spec 或 kubectl explain deployment.spec.strate ...
- k8s kubernetes 集群 证书更新操作
转载自https://www.cnblogs.com/kuku0223/p/12978716.html 1. 各个证书过期时间 /etc/kubernetes/pki/apiserver.crt #1 ...
- PAT归纳总结——关于模拟类问题的一些总结
关于时间的模拟问题 在刷题的过程中碰到了一些关于时间先后顺序的模拟题目,刚开始做的时候确实挺麻烦的,今天把这类问题的解题思路来整理一下. 比较典型的有: 1017 Queueing at Bank 1 ...
- .Net之Docker部署详细流程
开篇语 自己从头开始走一遍docker部署.net的流程,作为一种学习总结,以及后续会写一些在该基础之上的文章. 本次示例环境:vs2019.net5.docker.postman 创建项目 本次事例 ...
- css单位介绍em ex ch rem vw vh vm cm mm in pt pc px
长度单位主要有以下几种em ex ch rem vw vh vm cm mm in pt pc px %,大概可以分为几种"绝对单位"和"相对单位"和" ...
- animation几个比较好玩的属性(alternate,及animation-fill-mode)
<!DOCTYPE html> <html> <head> <style> div { width:100px; height:100px; backg ...
- 怎样用SQL修改某个字段的部分内容
方法:update dede_addonarticle set body = replace(body,'#p#分页标题#e#',' ') where body like '%#p#分页标题#e#%'