生成器
生成器
生成器的本质就是迭代器
生成器的表现形式
生成器函数
生成器函数 —— 本质上就是我们自己写得函数
生成器表达式
生成器函数:
含有 yield 关键字的函数就是生成器函数
特点:
调用函数的之后函数不执行,返回一个生成器
每次调用 next 方法的时候会取到一个值
直到取完最后一个,在执行 next 会报错
从生成器中取值的几个方法
1、next
2、for
3、数据类型的强制转换:占用内存 print(list(g))
生成器函数
我们先来看下普通函数
def generator(): print(1) return \'a\' ret = generator() print(ret)
接着来看生成器函数
#只要含有yield关键字的函数都是生成器函数 # yield 不能和 return 共用且需要写在函数内 def generator(): print(1) yield \'a\' #生成器函数:在执行之后会得到一个生成器作为返回值 ret = generator() #此处的 ret 是一个生成器而不是值了 print(ret) #此处在同过原来的调用方法调用的是内存地址 print(ret.__next__()) #通过 .__next__() 来调用函数的输出内容
下面来看一个生成器函数的例子
#在取值时 会取到第一个 yield 时停止,然后等待下一次取值的动作开始,继续取值到下一个 yield def generator(): print(1) yield \'a\' print(2) yield \'b\' print(3) yield \'c\' g = generator() ret = g.__next__() #单独执行第一次时:1 a print(ret) ret = g.__next__() #即:可以控制执行的位置 print(ret) ret = g.__next__() print(ret) for i in g: #使用 for 循环也同样可以 print(i) #但 for 循环不可以控制执行位置
写一个函数 制造 200w 个娃哈哈
ef wahaha(*args): for i in range(2000000): yield "娃哈哈%s"%i ret = wahaha(1000) #调用 #for i in ret: # print(i) #调用前 50 个 count=0 for i in ret: print(i) count+=1 if count > 50: break print(ret.__next__()) #这里一起执行会接着 for 循环调用 ret ,返回第 51个
监听文件输入的例子
#当检查到文件中有输入含有 python 字符时就会在屏幕上打印 def tail(filename): f = open(filename,encoding=\'utf-8\') #文件句柄 while True: line = f.readline() if line.strip(): yield line.strip() ret = tail(\'D:/py/log/test.txt\') for i in ret: if \'python\' in i: print(\'***\',i)
生成器函数进阶
关键字 send 的使用
#send 获取下一个值的效果和 next 基本一致 #只是在获取下一个值的时候,给上一 yield 的位置传递一个数据 #使用 send 的注意事项 # 使用生成器取第一个值的时候 必须用 next 来取值 # 最后一个 yield 不能接受外部的值 def generator(): print(123) content = yield 1 print(\'=====\',content) print(456) yield 2 g = generator() ret = g.__next__() print(\'***\',ret) ret = g.send(\'hello\') #向函数 content 的位置传值 print(\'***\',ret)
获取移动平均值(每次输入一个值都会计算出一个平均值)
10 20 30 10
10 15 20 17.5
avg = sum/count
def average(): sum = 0 count = 0 avg = 0 while True: num = yield avg sum +=num count += 1 avg = sum/count avg = average() avgs = avg.__next__() avgs = avg.send(10) avgs = avg.send(30) avgs = avg.send(60) avgs = avg.send(60) print(avgs)
预激生成器的装饰器
获取移动平均值进阶与装饰器的使用
#装饰器的作用就是在用户使用时,少写一句 ret = g.__next__() 方便操作 def init(func): def inner(*args,**kwargs): ret = func(*args,**kwargs) ret.__next__() return ret return inner @init def average(): sum =0 count = 0 avg = 0 while True: num = yield avg sum += num count += 1 avg=sum/count avg = average() ret = avg.send(10) ret = avg.send(20) ret = avg.send(60) print(ret) ret = avg.send(20) ret = avg.send(20) print(ret)
from 关键字的使用
#先来看一个 for 循环的例子,取出字符串中所有的单个字符 def generator(): a = \'abcde\' b = \'12345\' for i in a: yield i for i in b: yield i g = generator() for i in g: print(i) #使用 from 关键字取出 def generator(): a = \'abcde\' b = \'12345\' yield from a yield from b g = generator() for i in g: print(i)
生成器的表达式
来看简单的生成器表达式的例子
g = (i for i in range(10)) ret = g.__next__() print(ret) for i in g: print(i) 老母鸡=(\'鸡蛋%s\'%i for i in range(10)) #生成器表达式 print(老母鸡) for 蛋 in 老母鸡: print(蛋) g = (i*i for i in range(10)) g.__next__() for i in g: print(i) \'\'\' 生成器表达式与列表推导式的区别 1、括号不一样(列表为:[],生成器为:()) 2、返回的值不一样 === 几乎不占用内存 \'\'\'
各种推导式
包括:生成器 列表 字典 集合
生成器表达式与列表表达式语法一样 换个括号基本就 ok
作用:遍历操作、筛选操作
[每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据类型] —— 遍历之后挨个处理
[满足条件的元素相关的操作 for 元素 in 可迭代数据类型 if 元素相关的条件] —— 筛选功能
列表推导式例子
# 30以内所有能被3整除的数 ret = [i for i in range(30) if i%3 == 0] print(ret) # 30以内所有能被3整除的数的平方 g = [i*i for i in range(30) if i%3 ==0] print(g) \'\'\' # 找到嵌套列表中名字含有两个‘e’的所有名字 names = [[\'Tom\', \'Billy\', \'Jefferson\', \'Andrew\', \'Wesley\', \'Steven\', \'Joe\'], [\'Alice\', \'Jill\', \'Ana\', \'Wendy\', \'Jennifer\', \'Sherry\', \'Eva\']] e = [name for lis in names for name in lis if name.count(\'e\') == 2] print(e)
字典推导式例子
#例一:将一个字典的key和value对调 效果:{10:\'a\' , 34:\'b\'} mcase = {\'a\': 10, \'b\': 34} mcase_frequency = {mcase[k]: k for k in mcase} print(mcase_frequency) # 例二:合并大小写对应的value值,将k统一成小写,效果:{\'a\':10+7,\'b\':34,\'z\':3} 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)
集合推导式
#集合推导式,自带结果去重功能 squared = {x**2 for x in [1, -1, 2]} print(squared)