🍖生成器

一.什麼是生成器 (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
'''
------------------------------------------------------------
🍔一、"iter_obj=obj.__iter__()" 拿到迭代器
🍔二、觸發 "iter_obj.__next__()" 拿到該方法的返回值,賦值給item
🍔三、周而復始,直到函數內不在有 "yield", 即取值完畢
🍔四、"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 : 執行一次python

  • send : send 會傳送一個值給 yield 關鍵字, 賦值給 yield 左邊的的變量名, 再執行等同於 next 的功能繼續執行下面的代碼函數

  • close : 當使用 close 時, 會關閉生成器, 沒法在進行迭代取值, 取值則報 StopIteration 異常code

  • 喂狗示例: 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"
相關文章
相關標籤/搜索