一 生成器

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. 四、python学习-正则表达式

    正则表达式 import re lst = re.findall(正则表达式,需要匹配的字符串) findall 把所有匹配到的字符串都搜出来,返回列表 不能把分组内容和匹配内容同时显示出来 sear ...

  2. 简述Java多线程(二)

    Java多线程(二) 线程优先级 Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行. 优先级高的不一定先执行,大多数情况是这样的. 优 ...

  3. Zookeeper基础原理&应用场景详解

    简单了解Zookeeper Tips: 如果之前对Zookeeper不了解的话,这里大概留个印象就好了 Zookeeper是一个分布式协调服务,可以用于元数据管理.分布式锁.分布式协调.发布订阅.服务 ...

  4. 解决WebStorm无法正确识别Vue3组合式API的问题

    1 问题描述 Vue3的组合式API无法在WebStorm中正确识别,表现为defineComponent等无法被识别: 2 尝试方案 猜想这种问题的原因是无法正确识别对应的Vue3库,笔者相信Web ...

  5. 华为应用市场AppGallery Connect正式推出全新LOGO

    华为应用市场AppGallery Connect(简称AGC)正式推出全新Logo,新Logo的设计灵感源于编码中的符号<>,两个括号紧密联结成一个正方形,寓意华为应用市场AGC与开发者深 ...

  6. Day13_71_线程同步(synchronized)

    线程同步 * 异步编程模型和同步编程模拟的区别? - 有T1和T2 两个线程 > 异步编程模型:T1线程执行T1的,T2线程执行T2的,谁也不等谁 > 同步编程模型:T1和T2 线程执行, ...

  7. C#入门到精通系列课程——第1章软件开发及C#简介

    ◆本章内容 (1)了解软件 (2)软件开发相关概念 (3)认识.NET Framework (4)C#语言 (5)Visual Studio 2017 ◆本章简述 软件在现代人们的日常生活中随处可见, ...

  8. 一款轻量级的声明式http调用工具!

    前沿 项目中我们经常会使用HTTP工具向外部的REST接口发送请求,大家一般使用Okhttp,或者java的HttpClient发起,今天给大家介绍一款轻量级声明式的Http库(FeignClient ...

  9. PHP程序员要掌握哪些技术

    PHP程序员要掌握哪些技术 第一阶段: (PHP+MySQL核心编程)面向对象编程MySQL数据库,MySQL的优化细节.HTTP协议,http也是我们web开发的基石.对我们了解PHP底层机制有很大 ...

  10. Python中pip安装报错Unable to create process using '....'

    因为我本人在电脑上安装了python2和python3,所以在安装的时候,把两个python的安装目录都安装到G盘了.然后两个python的执行文件分别改成了 python2.exe 和  pytho ...