---恢复内容开始---
回顾下的 迭代器:
可迭代协议:内部含有__iter__()方法的值/变量都是可迭代的
可迭代变量 点__iner__()返回一个迭代器
迭代器特点: 节省内存,惰性运算,一次取值,只按照顺序取
所有的迭代器都是可迭代,反之 不成立
for循环和迭代器的关系,无论是迭代器换是可迭代都可以被for循环,
如果直接循环迭代器 循环一次就没了
如果循环非迭代器,那么每次循环都相当于从头到尾的循环
是因为在for循环中的所有非迭代器都会通过iter生成一个新的迭代器
一 生成器 (本质就是迭代器,生成器由生成器函来创建或者通过生成器表达式来创建)
1.先看简单函数
def func(): print("111") return 222 ret = func() # 结果为111 print(ret) # 结果为222
简单来说将函数中的return换成yield就是生成器:
def func(): print("111") yield 222 ret = func() print(ret) #此时结果为 <generator object func at 0x000001C11A730EB8> 生成器地址
生成器的本质是迭代器. 所以. 我们可以直接执行__next__()来执行
def func(): print("111") yield 222 gener = func() # 结果 111 这个时候函数不会执⾏. 而是获取到生成器器 ret = gener.__next__() # 这个时候函数才会执行. yield的作用和return一样. 也是返回 数据 print(ret) #结果222
简单例子 :
def funt(): # lst=[] # for i in range(10000): # lst.append("衣服%s" % i) # return lst # lst=funt() # print(lst) #得到10000件衣服 没地方放 换得找个仓库 :占内存
优化
def funt(): for i in range(10000): yield "衣服%s" % i gen=funt() # print(gen) a1=gen.__next__() a2=gen.__next__() a3=gen.__next__() a4=gen.__next__() a5=gen.__next__() a6=gen.__next__() print(a1) print(a2) print(a3) print(a4) print(a5) print(a6) # 要几件拿几件 不够 我想成批拿
再优化:
ef funt(): lst=[] for i in range(1,10000): lst.append( '衣服%s' % i) if i%50==0: yield lst lst=[] ret=funt() #生成器 a=ret.__next__() print(a) a2=ret.__next__() print(a2)
def func(): for i in range(1, 10000): yield "衣服%s" % i ret=func() for i in range(50): a=ret.__next__() print(a,end='')
生成器:本质是迭代器, 写法和迭代器不一样. 用法和迭代器一样
# 生成器函数: 函数中带有yield, 执行生成器函数的时候返回生成器。而不是执行这个函数
# def func():
# print("你好啊, 我叫赛利亚,")
# yield "西岚的武士刀" # return 和yield都可以返回数据
#
# ret = func() # generator ret是一个生成器
# print(ret)
# s = ret.__next__() # 当执行到__next__()的时候, 函数才真正的开始执行
# print("接受到的是", s)
例子2..
def func(): print("打开手机") print("打开陌陌") yield "手机" print("约妹子") print("出来喝喝茶") yield "电脑" print("我加了一句话") gen = func() # 生成器 ret1 = gen.__next__() print(ret1) ret2 = gen.__next__() print(ret2) ret3 = gen.__next__() # 找不到最后一个yield 会报错 print(ret3)
2.send () : send() 也可以实现类似__next__()的效果, send()可以给上一个yield传值
def func(): print("韭菜盒子") a = yield "哇哈哈" print("肉包子", a) b = yield "脉动" print("锅包肉", b) yield "冰红茶" gen = func() ret = gen.__next__() print(ret) ret = gen.send("刘伟") # 给上一个yield传值 print(ret) ret = gen.send("刘德华") # 给上一个yield传值 print(ret)
结果:
韭菜盒子
哇哈哈
肉包子 刘伟
脉动
锅包肉 刘德华
冰红茶
send()和__next__()的区别:
send()不可以用在开头
send可以给上一个yield传值,不能给最后一个yield传值
返回值写法:
def func(): yield "麻花藤" yield "李彦宏" yield "马云" yield "刘强东" gen=func() # a=gen.__next__() # print(a) print(gen.__next__()) # 麻花藤 print(gen.__next__()) #李彦宏" print(gen.__next__())#马云"
生成器本质是迭代器
print("__iter__" in dir(gen)) #所以可以使用for循环
for el in gen:
print(el)
lst = list(gen) # 把生成器中的每一个数据拿出来组合成一个列表
# print(lst)
二 推导式:
列表的推倒式:[结果 for循环 if筛选]
例子1
常规算法
lst = [] for i in range(1, 15): lst.append(i) print(lst)
推倒式写法:
lst = [i for i in range(1, 15)]
print(lst)
# 获取1-100内能被3整除的数
lst = [i for i in range(1, 101) if i % 3 == 0]
100以内能被3整除的数的平⽅
lst = [i*i for i in range(1, 101) if i % 3 == 0]
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven','Joe'], # ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']] 寻找名字中带有两个e的⼈的名字 lst = [name for first in names for name in first if name.count("e") >= 2 ] # print(lst) for name in names: # for nam in name: # if nam.count('e')>=2: # print(nam)
字典推倒式 {key: value for循环 if 筛选}
ic={"张无忌":'九阳神功',"乔峰":"收音机","楚留香":'帅'} # d={dic[k]:k for k in dic} # print(d)
lst1 = ["东北", "陕西", "山西", "开封", "杭州", "广东", "济南"]
# lst2 = ['大拉皮', "油泼面", "老陈醋", "灌汤包", "西湖鲤鱼", "早茶", "胶东一锅鲜"]
dic = {lst1[i]:lst2[i] for i in range(len(lst1))} # print(dic) dic={} for i in range(len(lst1)): for a in range(len(lst2)): dic[lst1[i]]=lst2[i] print(dic)
集合推倒式 (无序 不重复 可哈西) {key for if}
lst = ["周杰伦","周伯通","周润发","周伯通","周笔畅","周伯通","周星驰","周伯通"] # s = {el for el in lst} # print(s)
三 生成器表达式( 生成器表达式可以直接创建生成器)
gen = (i for i in range(10)) # generator
print(gen.__next__())
print(gen.__next__())
print(gen.__next__()) #结果 0 1 2
print('__iter__'in dir(gen)) # true
生成器表达式: 记录一下代码。 然后每次需要的时候去生成器中执行一次这个代码
# 列表推导式: 一次性把所有的数据创建出来, 容易产生内存浪费
# 特性:
# 1. 节省内存
# 2. 惰性机制
# 3.只能向前。
---恢复内容结束---