1、生成器
一、什麼是生成器?html
能夠理解爲一種數據類型,這種數據類型自動實現了迭代器協議(其餘數據類型須要調用本身內置的__iter__方法),因此生成器就是可迭代對象;python
二、生成器在python中的表現形式?程序員
- 生成器函數:常規函數定義,可是使用yield語句而不是使用retum語句返回結果,yield語句一次返回一個結果,在每一個結果中間掛機函數的狀態,以便下次從他離開的地方執行;
- 生成器表達式:相似於列表推導,可是生成器返回按須要產生結果的一個對象,而不是一次構建一個列表
#生成器函數(只要函數內部包含有yield關鍵字,那麼函數名()的到的結果就是生成器,而且不會執行函數內部代碼) cp = [1,2,3,4,5] def test(): yield 1 yield 2 yield 3 date = test() print(next(date)) print(next(date)) print(next(date)) 生成器函數
#三元表達式 name = "lw" res = "sb" if name == "lw" else "帥哥" print(res) egg1 = ["雞蛋 %s" %i for i in range(10) if i > 5 ] print(egg1) #正常列表(在內存中存儲) egg_list = [] for i in range(10): egg_list.append("雞蛋 %s" %i) print(egg_list) #列表解析(在內存中存儲) egg = ["雞蛋 %s" %i for i in range(10)] print(egg) #生成器表達式(基於迭代器協議轉換成可迭代對象,不佔內存) laomuji = ("雞蛋 %s" %i for i in range(10)) print(laomuji) #<generator object <genexpr> at 0x000001A6F46231A8> print(laomuji.__next__()) #等於next(laomuji) 生成器表達式
三、生成器取值的幾種方式app
- 直接調用生成器內置的__next__方法;生成器內的數據取完,在取會拋出StopIteration
def func(): print(1) yield 5 # 個人函數走到這了 print(2) yield 9 # 個人函數走到這了 g = func() # 生成一個生成器 print(g.__next__()) print(g.__next__()) # 每次取值會從上一個yield開始 print(g.__next__()) # 生成器內的數據取完,在取會拋出StopIteration next方法
- 生成器調用send()方法,send()至關於(next + 傳值),傳值給yield,第一次調用生成器的時候使用send裏邊的值必須是None
def func(): print(1) a = yield 2 # 1.掛起 2.返回值 3.接受值 print(a) print(3) b = yield 4 print(b) c = yield 9 g = func() # 生成一個生成器 print(g.__next__()) print(g.send('123')) print(g.send('234')) #第一次調用生成器的時候使用send裏邊的值必須是None send方法
四、簡述yield與yield from的區別ide
def generator(): for i in range(5): yield i t = generator() print(t.__next__()) def generator_1(): yield 1 yield 2 yield 3 yield 4 yield 5 t1 = generator_1() print(t1.__next__()) 上面這兩種方式是徹底等價的,只不過前者更簡單一些。 yield
def generator1(): item = range(10) for i in item: yield i def generator2(): yield ‘a‘ yield ‘b‘ yield ‘c‘ yield from generator1() #yield from iterable本質上等於 for item in iterable: yield item的縮寫版 yield from [11,22,33,44] yield from (12,23,34) yield from range(3) for i in generator2() : print(i) 從上面的代碼能夠看書,yield from 後面能夠跟的式子有「 生成器 元組 列表等可迭代對象以及range()函數產生的序列」 yield from
def test(): for i in range(10): yield i a = test() print(a.__next__()) for j in a: print(j) def test(): yield from range(10) b = test() print(b.__next__()) for j in b: print(j)
2、推導式
# 推導式:
# 1.列表
# 2.集合
# 3.字典
# 4.生成器表達式(只要是小括號的就是生成器表達式)li = [] for i in range(10): li.append(i) print(li) print([i for i in range(10)]) [結果 語法] #容器 li = [] for i in range(10): if i%2 == 1: li.append(i) print(li) print([i for i in range(10) if i%2 == 0]) # 過濾(篩選) li = [] for i in range(10): for em in range(3): li.append(em) print(li) print([j for i in range(10) for em in range(3) for j in range(5)]) 集合推導式 s = {i for i in range(10)} print(s) 字典推導式 print({i:i+1 for i in range(10)}) 生成器表達式 g = (i for i in range(10))
總結:函數
# 1.生成器的本質就是一個迭代器 # 2.生成器必定是一個迭代器,迭代器不必定是一個生成器 # 3.生成器是可讓程序員本身定義的一個迭代器 # 4.生成器的好處,節省內存空間 # 5.生成器的特性 一次性的,惰性機制,從上向下 # 6.send至關於 next+傳值,第一次觸生成器的時候,若是使用send(None)值必須是None,通常我建議大家使用__next__ # 7. python2 iter() next() # python3 iter() next() __next__() __iter__() # 8.yield from 將可迭代對象元素逐個返回
- 生成器調用send()方法,send()至關於(next + 傳值),傳值給yield,第一次調用生成器的時候使用send裏邊的值必須是None
- 直接調用生成器內置的__next__方法;生成器內的數據取完,在取會拋出StopIteration