当前位置:
首页 > Python基础教程 >
-
python基础教程之python摸爬滚打之day12----生成器,
1、生成器
生成器的本质就是迭代器.
1.1 获取生成器
1: 生成器函数
函数中出现 "yield" 的函数就是一个生成器函数, 再次执行函数时就不是运行函数而是获取生成器.
2: 生成器推导式
( i for i in range( 20) ) ----> 不是元组生成式, 而是生成器推导式, 它获取的是一个生成器.
gen = ( i for i in range( 20) ), gen就是一个生成器
1.2 生成器取值方式:
1, 通过__next__()取值. 2 , 通过send(" ")取值并传值.
1 def func(): 2 print("黄焖鸡") # 1 3 yield "黄焖鸡yield" # 2 4 print("烧鸭") # 3 5 yield "烧鸭yield" # 4 6 print("蒸鹿茸") # 5 7 yield "蒸鹿茸yield" # 6 8 print("蒸熊掌") 9 10 gen = func() # 函数中出现"yield" 时,表示该函数为生成器,获取生成器. 11 print(gen) # 结果是一个生成器地址. <generator object func at 0x000002798C873C78> 12 gen.__next__() # 取到函数体中yield的那行就停止(第1,2行),并将yield后面的内容返回给调用者 13 print(gen.__next__()) # 再次调用就从上次停止的yield下行(第3行)开始运行,截止到第四行. 14 print(gen.__next__()) 15 print(gen.__next__()) # 如果yield内容结束,还继续调用,则报错,但是print("蒸熊掌")还是会继续执行的
1.2 生成器本质就是迭代器, 如何满足迭代器的三个特点呢?
1 def buy(): 2 lst = [] 3 for i in range(1000): 4 lst.append("帽子%s" %(i)) # 把多有的帽子放在内存的列表里,占得内存大 5 return lst 6 print(buy()) 7 8 9 def buy_gen(): 10 for i in range(1000): 11 yield "帽子%s" %(i) # 不是一次性全部把帽子0.......帽子999放在内存, 12 # 而是通过__next__()一个一个取,比较省内存,但是不能往前执行, 13 # 满足迭代器的三个特点 14 gen = buy_gen() 15 print(gen.__next__()) 16 print(gen.__next__()) 17 print(gen.__next__()) 18 print(gen.__next__())
1 def baocaiming(): 2 print("蒸鹿茸") 3 a = yield "蒸鹿茸yield" 4 print("a=",a) 5 print("蒸熊掌") 6 b = yield "蒸熊掌yield" 7 print("b=", b) 8 print("烧花鸭") 9 c = yield "烧花鸭yield" 10 print("c=", c) 11 print("烧子鹅") 12 13 gen = baocaiming() 14 print(gen.__next__()) # 第一次只能用__next__()取值 15 print(gen.send("a++")) # 从上一次停止的yield开始执行,并将"a++"传给上次yield之前的变量a, a == "a++" 16 print(gen.send("b++")) 17 print(gen.send("c++")) # 函数里没有yield了,还继续调用,则报错,但是print("蒸熊掌")还是会继续执行的
send()取值方式机理?
2、各种推导式
2.1 列表推导式
[ 结果 for循环 if条件 ]
1 # 1到20 所有奇数的平方 2 lst = [i**2 for i in range(20) if i % 2 == 1] 3 print(lst) 4 5 # 将 a = [3,6,9] 转化成----> [(1,2,3),[4,5,6],[7,8,9]] 6 print([(ele-2,ele-1,ele-0) for ele in a]) 7 8 # 查找名字里面有两个"e"的名字 9 names = [ 10 ['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'], 11 ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva'], 12 ] 13 print([r for i in names for r in i if r.count("e") == 2])
2.2 字典、集合推导式
{结果 for循环 if条件}
1 dic = {"张无忌":"赵敏", "杨过":"小龙女", "郭靖":"黄蓉"} # 将键,值换成值,键 2 new_dic = {v:k for k,v in dic.items()} 3 print(new_dic) 4 5 # lst = [11, 22, 33] # => {0:11, 1:22, 2:33} 6 lst = [11, 22, 33] 7 dic = {i:lst[i] for i in range(len(lst))} 8 print(dic)
2.3 生成器推导式
(结果 for循环 if条件) 注意: 不是元组推导式, 元组是没有推导式!
生成器表达式和列表推导式有什么不同?
1: 列表推导式是一次性加载完, 耗内存; 生成器表达式几乎不占内存, 只有取值时候才分配和使用内存;
2: 列表推导式得到的是一个列表, 生成器表达式得到的是一个生成器.
2.4 生成器的惰性机制?
1 def func(): 2 print(111) 3 yield(222) 4 g = func() # 生成器 g 5 g1 = (i for i in g) # 生成器 g1, g1数据来源于g 6 g2 = (i for i in g1) # 生成器 g2, g2数据来源于g1 7 # --------------------------------截至到此,还没有生成器拿过值 8 # 惰性机制----只要不访问就永远拿不到值 9 print(list(g)) # ----> [222] 获取到g中的数据,此时才执行func()函数,将222返回给g. 10 print(list(g1)) # ----> [] list(g)已经将生成器g中的数据拿完了,所以g1拿不到数据,只能为[] 11 print(list(g2)) # ----> [] g2和g1一样,拿不到值. 12 13 # list() 的机理? (list()包含了for循环的机理) 14 # list() ----> 包含了for循环 ----> 通过__iter__()将可迭代对象转化成了 15 # 迭代器 ----> 通过__next__()从迭代器里取值 ----> 将拿到的值添加进列表里
2.5 yield from
把可迭代对象中的每一个元素作为生成器的结果返回.
1 def gen(): 2 lst = ["⿇花藤", "胡辣汤", "微星牌饼铛", "Mac牌锅铲"] 3 lst2 = ["饼铛还是微星的好", "联想不能煮鸡蛋", "微星就可以", "还可以烙饼"] 4 yield from lst # 把 lst中的每一个元素作为生成器的结果返回给调用者. 5 yield from lst2 # 两个yield不会产生交替的效果. 6 7 g = gen() 8 for el in g: 9 print(el)
栏目列表
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比
一款纯 JS 实现的轻量化图片编辑器
关于开发 VS Code 插件遇到的 workbench.scm.
前端设计模式——观察者模式
前端设计模式——中介者模式
创建型-原型模式