31 生成器

136次阅读
没有评论

共计 1839 个字符,预计需要花费 5 分钟才能阅读完成。

一. 什么是生成器 (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"
正文完
 
shawn
版权声明:本站原创文章,由 shawn 2023-06-16发表,共计1839字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)