python学习之生成器
4.6 生成器Generrator
生成器本质就是迭代器。python社区生成器与迭代器是一种。
生成器与迭代器的唯一区别:生成器是我们自己用python代码构建的
4.6.1生成器初识
python中的生成器:
1.生成器函数:使用yield语句而不是使用return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数状态,下次可以从它离开的地方继续执行,一个next引导一个yield。
2.生成器表达式:类似于列表推导,但是生成器返回按需产生结果的一个对象而不是一次构建一个结果列表。
本质:迭代器(自带_itr_ 和_next_方法)
特点:惰性运算
3.利用python提供的一些内置函数,返回一个生成器
4.6.2 生成器函数
一个包含yield关键字的函数就是一个生成器函数,用next触发,一个next对应一个yield。 只要函数中出现了yield那么他就不是函数,它是生成器函数。
def func():
yield 2, 3, 4
yield 'a'
yield [1,2,3]
ret = func() #注释1:
print(ret) #注释2:
print(next(ret))
print(next(ret))
print(next(ret))
#输出
<generator object func at 0x000001EB854B3FC0>
(2, 3, 4)
a
[1, 2, 3]
注释1:生成器对象,这里一定要声明一个变量指向生成器,直接print生成器的话,相当于在内存中新开辟空间调用生成器,print一次func() 就建立一个新的生成器,类似于多条产线同时生产一个物品一样,所以必须要有一个变量来指向生成器地址,目的是利用变量的唯一性特点。
注释2:print(ret)只是打印的ret指向的生成器地址,要显示生成器的结果,要用next来取值
4.6.3 yield 与 return的区别
return一般在函数中只设置一个,他的作用是终止函数,并且给函数的执行者返回值。
yield在生成器函数中可设置多个,他并不会终止函数,next会获取对应yield生成的元素。
4.6.4 send(了解)
send和next()区别:
相同点:
send 和 next()都可以让生成器对应的yield向下执行一次。
都可以获取到yield生成的值。
不同点:
第一次获取yield值只能用next不能用send(可以用send(None))。
send可以给上一个yield置传递值。
4.6.5 生成器举例
#1:单线程
def eat_food():
lis1 = []
for i in range(1,2001):
lis1.append(f"{i}份菜")
yield lis1 #即使yield在
s = eat_food()
print(next(s)) #输出['1份菜']
print(next(s)) #输出['1份菜', '2份菜']
#2:多线程,
def eat_food():
lis1 = []
for i in range(1,2001):
lis1.append(f"{i}份菜")
yield lis1
s = eat_food()
s1 = eat_food() #多线程下,交叉next不会冲突
print(next(s)) #输出['1份菜']
print(next(s1)) #输出['1份菜']
print(next(s)) #输出['1份菜', '2份菜']
print(next(s1)) #输出['1份菜', '2份菜']
#next配合for循环连续输出
def eat_food():
lis1 = []
for i in range(1,2001):
lis1.append(f"{i}份菜")
yield lis1
s = eat_food()
for i in range(200): #一次性输出200次
print(next(s))
4.6.6 yield与yield from
yield form可以直接把可迭代对象中的每一个数据作为生成器的结果进行返回。(python3中特有)
#先看yield
def func():
li = [1,2,3]
yield li
a = func()
print(next(a)) #输出[1, 2, 3]
#再看yield form
def func():
li = [1,2,3]
yield from li #将一个可迭代对象的每一个元素返回给next
a = func()
print(next(a)) #输出 1
print(next(a)) #输出 2
print(next(a)) #输出 3
有个小坑,yield from 是将列表中的每一个元素返回,所以如果写两个yield from 并不会产生交替的效果
def func():
lst1 = ['卫龙', '老冰棍', '北冰洋', '牛羊配']
lst2 = ['馒头', '花卷', '豆包', '大饼']
yield from lst1 #输出玩lst1才能输出lst2
yield from lst2
g = func()
for i in g:
print(i)
4.6.7 列表推导式,生成器推导式
1.列表推导式
- 列表推导式:一行代码构建一个有规律比较复杂的列表。
- 列表推导式与之前写法对比
#普通表达式
#生成1-100的列表l1 = [1,2,3......100]
l1 = []
for i in range(1,101):
l1.append(i)
print(l1)
# 列表推导式
l1 = [i for i in range(1, 101)]
print(l1)
2.列表推导式的两种构建方式
- 循环模式: [变量(加工后的变量) for 变量 in iterable]
- 筛选模式: [变量(加工后的变量) for 变量 in iterable if 条件]
# ----------------循环模式:------------
# 将10以内所有整数的平方写入列表。
print([i**2 for i in range(1, 11)])
# 100以内所有的偶数写入列表.
print([i for i in range(2, 101, 2)])
# 从python1期到python100期写入列表list
print([f'python{i}期' for i in range(1, 101)])
# ---------------筛选模式-------------:
# 三十以内可以被三整除的数。
print([i for i in range(1, 31) if i % 3 == 0])
# 过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母
l1 = ['barry', 'fdsaf', 'alex', 'sb', 'ab']
print([i.upper() for i in l1 if len(i) > 3])
# 找到嵌套列表中名字含有两个‘e’的所有名字(有难度)
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
print([j for i in names for j in i if j.count('e') > 1])
列表推导式的优缺点:
优点:
简单,快捷,装b。
缺点:
可读性不高,不好排错。
慎用,不要入迷。
3.生成器推导式
与列表推导式几乎一模一样,只是把[]换成()就行了。
循环模式,筛选模式。
#循环模式
tem = (i for i in range(10))
print(next(tem)) #输出 0
print(next(tem)) #输出 1
#筛选模式
tem = (i for i in range(10) if i%2==1)
print(next(tem)) #输出 1
print(next(tem)) #输出 3
#触发生成器
tem = (i for i in range(10) if i%2==1)
for i in tem:
print(i)
出发迭代器的几种方式:
1.next(tem)触发
2.for i in tem:
print(i)
因为for循环内部调用了next函数
3.转换生列表
print(list(tem))以列表的形式输出
4.6.8 字典推导式、集合推导式
两种模式: 循环模式,筛选模式
# 字典推导式
l1 = ['小潘', '小明','小红', '小强']
dic = {i:l1[i] for i in range(len(l1))}
print(dic)
#集合推到式
l1 = ['小潘', '小明','小红', '小强']
set1 = {i for i in range(len(l1))}
print(set1)
python学习之生成器的更多相关文章
- Python学习二(生成器和八皇后算法)
看书看到迭代器和生成器了,一般的使用是没什么问题的,不过很多时候并不能用的很习惯 书中例举了经典的八皇后问题,作为一个程序员怎么能够放过做题的机会呢,于是乎先自己来一遍,于是有了下面这个ugly的代码 ...
- python学习之---生成器
通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含1000万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元 ...
- Python学习笔记 - 生成器generator
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # generator 生成器 L = [x * x for x in range(10)] print( ...
- Python学习——迭代器&生成器&装饰器
一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素.迭代器仅 ...
- python学习-39 生成器总结
总结 1.语法上和函数类似:生成器函数和常规函数几乎是一样的.它们都是使用def语句进行定义,差别在于,生成器使用yield语句返回一个值,常规函数使用return语句返回一个值. 2.自动实现迭代器 ...
- python学习之- 生成器/迭代器
列表生成式写法: [ i*2 for i in range(10) ]也可以带函数 [ fun(i) for i in range(10) ] 生成器:一边循环一边计算的机制称为生成器.在常用函数中, ...
- Python学习---装饰器/迭代器/生成器的学习【all】
Python学习---装饰器的学习1210 Python学习---生成器的学习1210 Python学习---迭代器学习1210
- Python学习笔记之生成器、迭代器和装饰器
这篇文章主要介绍 Python 中几个常用的高级特性,用好这几个特性可以让自己的代码更加 Pythonnic 哦 1.生成器 什么是生成器呢?简单来说,在 Python 中一边循环一边计算的机制称为 ...
- python学习10—迭代器、三元表达式与生成器
python学习10—迭代器.三元表达式与生成器 1. 迭代器协议 定义:对象必须提供一个next方法,执行该方法或者返回迭代中的下一项,或者返回一个StopIteration异常,以终止迭代(只能往 ...
随机推荐
- JS---client系列
offset系列:获取元素的宽,高,left,top, offsetParent offsetWidth:元素的宽,有边框 offsetHeight:元素的高,有边框 offsetLeft:元素距 ...
- chattr&lsattr
chattr 和 lsattr 用来查看和改变文件属性,chmod 只是用来改变文件的读写与可执行权限,而文件的属性控制是由 chattr 来完成 常用用法: chattr +i /home/test ...
- 拒绝被坑!如何用Python和数据分析鉴别刷单!?
发际线堪忧的小Q,为了守住头发最后的尊严,深入分析了几十款防脱洗发水的评价,最后综合选了一款他认为最完美的防脱洗发水. 一星期后,他没察觉到任何变化. 一个月后,他用卷尺量了量,发际线竟然后退了0.5 ...
- NFS的搭建
NFS是Network File System的简写,即网络文件系统. 网络文件系统是FreeBSD支持的文件系统中的一种,也被称为NFS. NFS允许一个系统在网络上与他人共享目录和文件.通过使用N ...
- Python 操作 MySQL 数据库Ⅱ
数据库连接 连接数据库前,请先确认以下事项: 您已经创建了数据库 TESTDB. 在TESTDB数据库中您已经创建了表 EMPLOYEE EMPLOYEE表字段为 FIRST_NAME, LAST_N ...
- VM删除快照失败,磁盘空间不足,只是删除了快照名字(全网唯一解决办法)
原创: 删除之前的快照,发现只是把名字删除了, 看着这么多文件也不知道怎么删,一顿百度google也是没找到答案 于是就自己琢磨 因为删除快照的时候,是先把快照删除,然后删除无效的文件 所以先让这个盘 ...
- [HG]提高组 题解
首先很容易想到暴力DP 设状态f[i][j]表示当前放了第i个数,最大的数为j的方案数. 然后根据转移推出实际上是在下图走路的方案数 \[ \left( \left( \begin{matrix} x ...
- HDU 6669 Game
hdu题面 解题思路 首先我们要选一个起点,这个起点应该在第一个区间内,然后再看第二个区间在左边还是右边以便移动,但转念一想,我们可以把起点直接选在前一堆区间的交集上,于是思路就有了--依次把所有区间 ...
- JS Module
JS Module Summary I. Why we need to use the Module? In the past, Javascript can execute independentl ...
- js+jq 淡入淡出轮播(点击+定时+鼠标进入移出事件)
<!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title> ...