一、生成器简介

生成器:可以当做是一种数据类型,遵循迭代器协议,是一种可迭代对象。

特点:这种数据类型自动实现了迭代器协议,提供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 都可以遍历。

 

python迭代器与生成器 python中迭代器和生成器_生成器

python迭代器与生成器 python中迭代器和生成器_生成器_02

# 生成器函数 例:
# 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)