1生成器
1生成器的本质 一定是迭代器(反之不一定(用send(生成器特有方法)验证))
2生成器是可以让程序员自己定义的一个迭代器
3生成器的好处,节省内存空间
4生成器的特性,一次性的,惰性机制,从上往下
5send 相当于next + 传值,第一次出生成器的时候,如果使用send(这必须是None),建议开始__next__
6# python 2 next() iter() # python 3 next() iter() __next()__ __iter()__
7yield 将可迭代对象元素逐个返回
函数体存的是代
码 #存yield 的时候是生成器
函数生成生成器
def fun(): print(1) yield 4 g = fun()
#碰到return 就结束函数
#碰到 yield 就挂起
def fun(): print(1) return 2 def fun(): print(1) yield 4
三个错误分析
语法分析 语义分析 词法分析
生成器的两种情况
新建一个 用完就没 没了打错
def fun(): print(1) yield 4 #我的函数走到这 生成第一个 之前的清空了 print(2) yield 9 #第二部函数走到这 g = fun() #生成一个生成器 fun()# #生成一个生成器 print(g.__next__() ) print(g.__next__() )# yield后面的 # print(g.__next__() )#迭代器 惰性只能用一个
直接使用 永不枯竭
print(fun().__next__()) #fun() 这样生成 一个生成器 # print(fun().__next__()) print(fun().__next__())#fun()又重新生成一个生成器 若有多个yield 到不了第二个
print(list(range(10000)))
#浪费内存
生成器
非常节省内存
send
def fun(): print(1) a = yield 2#1挂起2返回值3接受值 print(a) print(2) a = yield 3 # print() c =yield 2 g = fun() print(g.__next__()) # 有括号执行 a = g.__next__() #接受值 print(a,'aa') #第一次使用生成器 不是只用next #第一次只能是None 如果非要传值 # print(g.send(None))#send = next + 传值 print(g.send('123'))#send = next + 传值 # print(g.__next__()) # print(g.send('234'))#send = next + 传值 # next + send = num(yield)
yiled from
只建一个新变量 和每次都建变量
def fun(): li = [1,2,3,4] yield from li ret = fun().__next__() print('ret is ', ret) ret = fun().__next__() print('ret is ', ret) a = fun() #把生成器地址给了a 和函数地址不一样 ret1 = a.__next__() # 执行ret 这个变量的指向的生成器地址 ret2 = a.__next__() print(ret1,ret2) print(a)
def fun(): li = [1,2,3,4] li1 = [9,6,7,7] # yield from li,li #会报错 yield from li #会报错 yield from li1 #会报错 ret = fun().__next__() print('ret is ', ret) ret = fun().__next__() print('ret is ', ret) ad = fun() #把生成器地址给了a 和函数地址不一样 ret1 = ad.__next__() # 执行ret 这个变量的指向的生成器地址 ret2 = ad.__next__() print(ret1,ret2) print(ad.__next__()) print(ad.__next__()) print(ad.__next__()) print(ad)
举例:
''' 在必应壁纸的组图,一个个是生成器的迭代 而不是所有的都加到前端,太大,加载速度慢'''
更乱的
def func(): if 2>1: print('这是逻辑1') yield True else: yield False g = fun() # while g.__next__(): # print(1) print('s '.strip(),1) s = 'ssss '.strip() print(s, 1) def funny(): with open('t','r',encoding='utf-8'): pass
推导式:
li = [] for i in range(10): li.append(i) print([i for i in range(10)]) #[结果 语法]# 容器 li = [] for i in range(10): if i%2 == 1: li.append(i) print(li) print([i for i in range(10)if i%2==1]) for i in range(10): for em in range(3): li.append(em) # 列表的 print([i for i in range(10)for em in range(3)]) # [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9] print([em for i in range(10)for em in range(3)]) # [0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2] print([j for i in range(10)for em in range(3)for j in range(5)])#30个 # [0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4] print(i for i in range(10)for em in range(3)) print(i) #9 # <generator object <genexpr> at 0x0000000001DE78E0> # 集合推导式 print({i for i in range(10)for em in range(3)}) # {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} # 字典推导式 print({i : i+1 for i in range(10)}) #{‘电脑’:‘998’,‘998’:1} # {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10} # 元组---没有 print((i for i in range(10)))#和上面的一样生成器 # 字符串也没有 print(i for i in 'adjaigia') #和上面的一样生成器 #生成器 g = (i for i in range(10)) a = g print(a.__next__()) print(a.__next__()) #1. 外部需要容器报一下, 里面的第一个位置 结果 剩下位置都是语句 #2. 推导式 ----面试 实现小的需求时 可以使用推导式,节省代码 #3. 不要写太长,可读性差
从文本里面读文件,生成器的方式读出来,不是一次性都读出来,用多少使多少>>>>>>
文本如下
adfadafadfadfa
fadfasdfafassdfada
adafdafadfadffasf
adfafdafadfafsdfadfadafadfadfa
adfadfasdfafassdf
adafdafadfadffasf
adfafdafadfafsdfadfadafadfadfa
adfadfasdfafassdf
adafdafadfadffasf
adfafdafadfafsdf
代码如下
def funny(): with open('t', 'r', encoding='utf-8') as f: for a in f: if a == '\n': del a #输出 多行 没输出a 的空行 但是也有空行输出 else: yield a.strip() #这样就没空格了 怎么删了两次 # print(f.read()) # yield from f.read() # 这个是读的什么 显示的是a \n b \n c\n # yield from f # 这个是读的什么 显示的是abcd 换好几行 在写 再换好几行 怎么执行完了还隔一行再写 g = funny().__iter__() #确实是对的 #最后是 传入元素里还含有空格 ,然后用 strip 删除 # 多个才能看出来 以后不能 只弄两个 空格也是输出 print(g.__next__(),end='这里') print('你是?',g.__next__(),'他是') print('你是?',g.__next__()) print(g.__next__()) #明明可以下面 非要上面 for i in range(10): print(g.__next__()) g = funny()#等于g = funny().__iter__() print(g.__next__())
生成器举例:
#写那个逻辑的 def func(): if 2 > 1: print('这是逻辑1') yield True else: yield False g = func() print(id(g))#34437344 # print(g.__next__()) while func().__next__(): #答案不一样 print(id(func())) #42333816 break print(1)