一、上节回顾:
1、可迭代对象:惰性运算 拥有__iter__方法
2、迭代器: 拥有__iter__和__next__方法
3、生成器:惰性运算,开发者自定义 本质:迭代器 所以拥有__iter__和__next__方法
惰性运算:不取值就不计算 且每一个值只能被取一次,取完为止
生成器的优点:延迟计算,一次返回一个结果,也就是说,它不会一次生成所有的结果,这对于大数据处理非常有用
生成器------迭代器:节省内存
1)生成器函数:
带有yield 关键字
执行函数之后的返回值是生成器,函数内的代码并不会真正执行
想让生成器吐出数据,需要使用next 方法,send, for循环
二、新内容
1、生成器的调用例子 取用:cloth
def cloth(): for i in range(100): yield "衣服%s"%i g=cloth() # 方法一 # for i in g: # print(i) # 方法二 for i in range(100): print(g.__next__())
2、监听文件末尾追加的例子
调用生成器并不执行,当取用的时候才会执行def下面的内容(Windows系统的时候才可以使用)
def tail(): f=open("你好.bak","r",encoding="utf-8") f.seek(0,2) while True: line=f.readline() if line: yield line import time time.sleep(0.1) g=tail() for i in g: print(i.strip())
3、send 和next 的范围是一样的
(1)从哪一个yield开始接着执行,就把一个值传给了那个yield
(2)send 不能用在第一个触发生成器,触发生成器第一个必须是__next__()
(3)生成器函数中有多少个yield就必须有多少个next+send
def func(): print("*"*10) a=yield 5 print(a) yield 10 g=func() num=g.__next__() print(num) num2=g.send("alex") print(num2) # ********** # 5 # alex # 10
def averager(): total=0.0 count=0 average=None while True: term=yield average total+=term count+=1 average=total/count g_avg=averager() g_avg.__next__() print(g_avg.send(10)) print(g_avg.send(20)) print(g_avg.send(30)) # 10.0 # 15.0 # 20.0
4、补充:python3 之后有的这个功能:yield from a
def func(): a="AB" b="CD" yield from a #for i in a:yield i yield from b #for i in b:yield i g_func=func() for i in g_func: print(i)
5、触发执行的方式
(1)生成器.__next__()
(2)生成器.send()
send(None)==__next__().
send在next的基础上传一个值到生成器函数的内部
send 操作不能用在生成器使用的第一次
以上两个执行几次拿几个数据,可能会遇到取完报错
(3)for循环 每次取一个,取完为止。for循环不会报错
6、总结:
生成器函数:生成一个生成器的函数
生成器的本质:参数迭代器
生成器函数的特点:(1)带有yield 关键字 (2)且调用之后,函数内的代码不执行
触发执行的方式:(1)next (2)send (3)for 循环
三、各种推导式
1、列表推导式:
y=[1,2,3,4,5,6,7] # 方法一 # x=[] # for i in y: # x.append(i**2) # print(x) # 方法二 x=[i**2 for i in y] print(x) # [1, 4, 9, 16, 25, 36, 49]
# x=[] # for i in range(100): # x.append(i/2) # print(x) x=[i/2 for i in range(100)] print(x)
2、生成器表达式 (生成器表达式+for循环节省内存 推荐使用)
#列表推导式 y=[1,2,3,4,5,6] x=[i**2 for i in y] #[ ] print(x) #生成器表达式 y=[1,2,3,4,5,6] g=(i**2 for i in y) #( ) print(g) for i in g: print(i)
l=["鸡蛋%s"%i for i in range(10)] print(l) lmuji=("鸡蛋%s"%i for i in range(10)) for egg in lmuji : print(egg)
3、补充:
并不是所有的都可以转换
g.__next__()==next(g ) g.__iter__()==inter(g)
4、30以内能被3整除的数的平方 列表推导式的例子
# 30以内能被3整除的数的平方 # x=[i**2 for i in range(30) if i%3==0] # print(x) def square(x): return x**2 x=[square(i) for i in range(30) if i%3==0] print(x)
5、字典推导式
dic={"a":10,"b":34} dic_fre={dic[k]:k for k in dic} print(dic_fre) #{10: 'a', 34: 'b'} key value 对换
mcase={"a":10,"b":34,"A":7,"Z":3} mcase_frequency={k.lower():mcase.get(k.lower(),0)+mcase.get(k.upper(),0)for k in mcase} print(mcase_frequency) #{'a': 17, 'b': 34, 'z': 3}
6、集合的推导式 去重
squared={x**2 for x in [1,-1,2]} print(squared) #set([1,4])
面试题: