• 🍖生成器


    一.什么是生成器 (generator)

    • 生成器就是一个自定义的迭代器
    • 函数体内含有 yield 关键字

    二.为何要使用生成器

    • 为了节省内存

    三.创建生成器的两种方式

    • 调用带 yield 关键字的函数
    • 使用生成器表达式

    四. yield 关键字

    • 函数体内但凡出现 yield 关键字
    • 调用函数将不会触发函数体代码的运行
    • 而是会返回一个生成器对象,生成器本质就是一个迭代器
    def chicken():
        print('=====>first')
        yield 1
        print('=====>sencond')
        yield 2
        print('=====>third')
        yield 3
    
    obj=chicken()
    print(obj)       # <generator object chicken at 0x000002CEE1A7AAC8> 是一个生成器, 一只老母鸡
    
    • 生成器本质就是迭代器,也就是说生成器的玩法其实就是迭代器的玩法
    print(obj.__iter__() is obj)  # True
    print(next(obj))              # =====>first    1
    print(next(obj))              # =====>sencond  2         
    print(next(obj))              # =====>third    3                   
    
    • 使用 for 循环来验证
    for item in obj:
        print(item)
    '''
    =====>first
    1
    =====>sencond
    2
    =====>third
    3
    '''
    ------------------------------------------------------------
    1、"iter_obj=obj.__iter__()" 拿到迭代器
    2、触发 "iter_obj.__next__()" 拿到该方法的返回值,赋值给item
    3、周而复始,直到函数内不在有 "yield", 即取值完毕
    4、"for" 会检测到 "StopIteration" 异常,结束循环
    

    五. yield 与 return 的区别

    1.相同点

    • 在返回值得角度, 用法都一样

    2.不同点

    • yield 可以返回多次值, 而 return 只能返回一次值

    3.总结 yield

    • 为我们提供了一种自定义迭代器的方式
    • yield 可以暂停函数, 保存函数执行的状态, 然后使用 next 方法再次触发函数体代码的运行 (协程知识点)

    4.应用示例

    • 造一个无穷值
    def my_range():
    	n = 0
    	while True:
    		yield n
    		n += 1
    obj = my_range()    # 一个生成器
    print(obj)          # <generator object my_range at 0x0000022784809F48>输出的是老母鸡内存地址
    
    使用"next"取值
    print(next(obj))    #  0
    print(next(obj))    #  1
    print(next(obj))    #  2
    print(next(obj))    #  3  
    ......等等..
    
    使用 "for" 循环
    for i in my_range():  # 也可以使用 for 循环取
        print(i)
    
    • 模仿内置函数 range( )
    def my_range(start, stop, step = 1):
    	n = start
    	while n < stop:
    		yield n
    		n += step
    使用 "next" 取值
    obj = my_range(2 ,14, 2)
    print(next(obj))     # 2
    print(next(obj))     # 4
    print(next(obj))     # 6
    
    使用 "for" 循环
    for line in my_range(2, 15, 3)
    	print(line)
    

    六. yield 的应用

    • next : 执行一次

    • send : send 会传送一个值给 yield 关键字, 赋值给 yield 左边的的变量名, 再执行等同于 next 的功能继续执行下面的代码

    • close : 当使用 close 时, 会关闭生成器, 无法在进行迭代取值, 取值则报 StopIteration 异常

    • 喂狗示例: ps : "dog.send(None)" 的效果等于 "next(dog)"

    def eat(name):
    	print('%s start eat' %name)
    	while True:
    		food = yield 1  # yield 接收 send 传过来的值赋值给 food
    		print('%s start eat %s'%(name,food))
    
    dog = eat('派大星的狗')   # 获得生成器
    
    next(dog)                # 派大星的狗 start eat
    dog.send("海绵宝宝")      # 派大星的狗 start eat 海绵宝宝  (send 自带 next 的执行功能)
    dog.close()              # 关闭这个生产器 (无法在进行取值)
    next(dog)                # 再次取值跑出异常 "StopIteration"
    
  • 相关阅读:
    317 随笔
    316 随笔
    315 随笔
    python 第一章
    matlab 第四章 第一节 字符串 元胞
    matlab 第三章 第二节 多维数组
    matlab 第三章
    python 循环+break continue
    Springboot 教程 导入
    matlab 第二章 第三节 数值表示、变量及表达式
  • 原文地址:https://www.cnblogs.com/songhaixing/p/14103590.html
Copyright © 2020-2023  润新知