一、生成器简介
生成器:可以当做是一种数据类型,遵循迭代器协议,是一种可迭代对象。
特点:这种数据类型自动实现了迭代器协议,提供next()方法
创建生成器对象的两种方式:
1、函数方式
使用 yield 作为函数的返回值。
2、生成器表达式
item=(i for i in range(10))
# 类似三元表达式
例:item_list = [i for i in range(10)]
注:这是比较好的编程习惯,但并不能应用在大量数据之中
3、总结
语法上:与函数类似,差别在生成器使用yeild语句作为返回值。
自动实现迭代器协议,不用像列表等数据类型执行iter方法,可以直接next。
状态挂起:生成器使用yeild语句返回一个值,yeild挂起该函数的运行状态,以便从上一次终止的状态继续运行。
优点:
1、延迟计算,优化数据处理,一次返回一个结果,而不是一次生成所有结果,占用大量内存。
2、提高代码可读性,(保证可读性的前提,减少代码量)
注意:生成器只能遍历一次,不止for循环能遍历生成器,其他函数如,list sum 都可以遍历。
# 生成器函数 例:
# import time
# def y_test():
# print("母鸡下蛋准备")
# time.sleep(3)
# yield "第一颗鸡蛋"
# time.sleep(3)
# yield "第二颗鸡蛋"
# time.sleep(3)
# yield "第三颗鸡蛋"
# res = y_test()
# print(res.__next__())
# print(res.__next__())
# print(res.__next__())
示例1:公鸡下蛋
二、生产者消费者模型
函数之间相互调用,等待切换,无形中窥探到了单线程,多并发。
import time
def produser(name):
print('%s 我开动了'%name)
for i in range(1,3):
time.sleep(2)
yield print("%s 吃了 %s 个包子" % (name, i)
time.sleep(2)
print('吃完了')
def consumer():
name="小智"
e = produser(name)
try:
while True:
next(e)
except StopIteration:
print("吃饱了")
consumer()
三、生成器练习之【模拟管道功能】tail -f access.log |'404:
# message.txt 文件内容
2022/1/15 09:18 192.168.1.103 watch AV.mv.mp4
2022/1/15 22:04 192.168.1.111 watch AV.mv
2022/1/16 07:20 192.168.0.12 watch AV.mv
# 代码
def my_tail(file): # tail 拿到文件最后一行的二进制内容
with open(file,'rb',) as data:
data.seek(0,2) # 移动到文件的最后一行
while True:
line = data.readline() # line 等于 最后一行的行内容
if line: # 判断是否为空行
yield line # 如果不是空行,返还 行内容给 line —> my_tail 等待继续调用
else:
time.sleep(2) # 如果为空行的,休息2秒再进行判断
def my_grep(err_msg,tail): # 传入 错误信息 、 tail 函数(拿到文件最后一行内容)
for i in tail: # 循环 tail传入的 最后一行内容
line = i.decode() # 解码 该行内容 赋值给 line
if err_msg in line: # 如果传入的 err_msg 在 line 里
yield line # yield 的返回值为 line 传入—> my_grep 然后等待下一次调用。
for i in my_grep("带病毒的软件",my_tail('message_log.txt')): #过滤带病毒的软件
print(i)