一 生成器

1.1 基本概念

元组推导式是是生成器(generator)

生成器定义

  • 生成器可以实现自定义,迭代器是系统内置的,不能够更改
  • 生成器的本质就是迭代器,只不过可以自定义.

生成器有两种定义的方式:

  1. 生成器表达式 (里面是推导式,外面用圆括号)
  2. 生成器函数

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区别:

  1. next 只能取值
  2. send 不但能取值,还能发送值

send注意点:

  1. 第一个 send 不能给 yield 传值 默认只能写None (语法的硬性要求)
  2. 最后一个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

最新文章

  1. 百度推出新技术 MIP,网页加载更快,广告呢?
  2. 我JSP学习心得1
  3. js 实现进度条功能。
  4. iOS 7 与 Xamarin - MultiPeer Connectivity(转载)
  5. 【前端也要学点算法】快速排序的JavaScript实现
  6. hdu1162(最小生成树 prim or kruscal)
  7. Jqgrid 数据格式化配置
  8. The Ninth Hunan Collegiate Programming Contest (2013) Problem A
  9. 【Android Api 翻译4】android api 完整翻译之Contacts Provider (学习安卓必知的api,中英文对照)
  10. 通过 监听器获取sessionId
  11. 获取bundle目录下的所有图片文件名
  12. dnf脚本的研究
  13. Java 如何连接 SQL 2008 R2
  14. VB.NET 机房收费系统项目总结
  15. 用python计算lda语言模型的困惑度并作图
  16. PKU-1704-Georgia and Bob
  17. Java基础总结--Java编程环境变量配置
  18. 5秒让你的View变3D,ThreeDLayout使用和实现
  19. python实现获取身份证号码的方法
  20. Django的安装

热门文章

  1. 201871030126-王会娟 实验二 个人项目—《D{0-1} KP》项目报告
  2. 考前自救题库NABCD分析
  3. OO第二章总结
  4. OO_Unit1_表达式求导总结
  5. Spring Boot demo系列(六):HTTPS
  6. matlab结构体、数组和单元数组类型的创建
  7. WebGL之绘制三维地球
  8. 【Spring】SpringIoC大致流程
  9. 概A第二章测试
  10. 基于IMU与磁力计的手势提取手套-原理及其实现