一 生成器

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

020.Python生成器和生成器函数的更多相关文章

  1. python迭代器和生成器(3元运算,列表生成式,生成器表达式,生成器函数)

    1.1迭代器 什么是迭代器: 迭代器是一个可以记住遍历的位置对象 迭代器对象从集合的第一个元素元素开始访问,直到所有元素被访问完结束,迭代器只能往前不会后退. 迭代器有两个基本方法:iter ,nex ...

  2. python中的生成器函数是如何工作的?

    以下内容基于python3.4 1. python中的普通函数是怎么运行的? 当一个python函数在执行时,它会在相应的python栈帧上运行,栈帧表示程序运行时函数调用栈中的某一帧.想要获得某个函 ...

  3. python学习 day11 (3月16日)----(生成器内置函数)

    1生成器 1生成器的本质 一定是迭代器(反之不一定(用send(生成器特有方法)验证))2生成器是可以让程序员自己定义的一个迭代器3生成器的好处,节省内存空间4生成器的特性,一次性的,惰性机制,从上往 ...

  4. 【学习笔记】--- 老男孩学Python,day13 生成器,生成器函数,各种推倒式和生成器表达式

    1. 生成器和生成器函数 生成器的本质就是迭代器 生成器的三种创建办法: 1.通过生成器函数 2.通过生成器表达式创建生成器 3.通过数据转换   2. 生成器函数: 函数中包含了yield的就是生成 ...

  5. Python进阶(四)----生成器、列表推导式、生成器推导式、匿名函数和内置函数

    Python进阶(四)----生成器.列表推导式.生成器推导式.匿名函数和内置函数 一丶生成器 本质: ​ 就是迭代器 生成器产生的方式: ​ 1.生成器函数

  6. Python入门篇-生成器函数

    Python入门篇-生成器函数 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.生成器概述 1>.生成器generator 生成器指的是生成器对象,可以由生成器表达式得到, ...

  7. python之序列去重以及生成器、生成器函数、生成器表达式与迭代器浅谈

    首先要明确序列值类型是否可哈希,因为可哈希的值很简单就可以用 in /not in 写个生成器去判断,如果是不可哈希的就要去转换为可哈希的再用 in/not in 去判断 原地不可变类型(可哈希): ...

  8. python之迭代器 生成器 枚举 常用内置函数 递归

    迭代器 迭代器对象:有__next__()方法的对象是迭代器对象,迭代器对象依赖__next__()方法进行依次取值 with open('text.txt','rb',) as f: res = f ...

  9. Python第六章-函数05-迭代器&生成器

    python作为一个既面向对象,又支持函数式编程的语言,函数的使用方面有很多特点. 比如:闭包,装饰器,迭代器等 函数的高级应用 容器:生活中常见的容器有哪些?袋子,盆子,水杯,书包,铅笔盒... 容 ...

随机推荐

  1. OGG-集成模式抽取与数据库参数streams_pool_size关系

    一.学习目标 Oracle数据库,使用OGG集成模式抽取进程启动时,如果没有配置合理的streams_pool_size参数可能会过一段时间就报错abend! 那么我们如何配置这个参数的大小?如何计算 ...

  2. (十一)struts2的未知处理器

    从struts2.1开始,struts2增加了未知处理器. 当用户请求未知Action,或指定Action里的未知方法,或Action处理结束后返回一个未知的result.struts2允许使用未知处 ...

  3. JVM(三)类加载与字节码技术

    1.类文件结构 首先获得.class字节码文件 方法: 在文本文档里写入java代码(文件名与类名一致),将文件类型改为.java 在文件对应目录下运行cmd,执行javac XXX.java 以下是 ...

  4. SpringBoot+Dubbo+Zookeeper 实例

    前言 当下Java 生态环境里面,微服务占据了非常大的份额,现在大部分新开发的 Java选型的后台程序都很奇妙的会跟微服务发生一些关系.那目前市面上主流的微服务方向主要有 Spring 家族推出的Sp ...

  5. 华为云PB级数据库GaussDB(for Redis)揭秘第八期:用高斯 Redis 进行计数

    摘要:高斯Redis,计数的最佳选择! 一.背景 当我们打开手机刷微博时,就要开始和各种各样的计数器打交道了.我们注册一个帐号后,微博就会给我们记录一组数据:关注数.粉丝数.动态数-:我们刷帖时,关注 ...

  6. Spring Boot demo系列(三):Spring Web+MyBatis Plus

    2021.2.24 更新 1 概述 Spring Web+MyBatis Plus的一个Demo,内容和上一篇类似,因此重点放在MyBatis Plus这里. 2 dao层 MyBatis Plus相 ...

  7. 详解Linux指令与文件的搜寻

    我们在管理Linux服务器时通常会进行搜索文件及目录操作,下面我们就开始了解一下linux目录结构的相关知识. 博主再奉上一套零基础入门Linux视频,带你从入门到精通 https://www.bil ...

  8. kubespray续签k8s证书

    查看证书过期时期 [root@node1 ~]# openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text |grep ' Not ...

  9. 三个dom xss常用tips

    分享dom xss的三个案例 (1)javascript里面过滤单引号和双引号? 搭建环境: 只是过滤了单引号和双引号是可以xss的: 使用<>闭合script即可 </script ...

  10. 针对中国政府机构的准APT攻击样本Power Shell的ShellCode分析

    本文链接网址:http://blog.csdn.net/qq1084283172/article/details/45690529 一.事件回放 网络管理员在服务器上通过网络监控软件检测到,有程序在不 ...