🍖生成器

一.什么是生成器 (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"
原文地址:https://www.cnblogs.com/songhaixing/p/14103590.html