1. 程式人生 > >python 生成器 和生成器函式 以及各種推導式

python 生成器 和生成器函式 以及各種推導式

一.生成器    本質就是迭代器. 我們可以直接執⾏__next__()來執⾏ 以下⽣成器 一個一個的建立物件 建立生成器的方式: 1.生成器函式 2.通過生成器 表示式來獲取生成器 3.型別轉換(看不到) 二.生成器函式(重點)    深坑:生成器在要值得時候才拿值 生成器函式中包含yield,返回資料和return差不多:return會立即結束這個函式的執行,yield 表示返回,不會終止函式的執行,可以分段的執行一個函式. 當函式中包含了yield,次函式就是生成器函式 坑:生成器函式在執行的時候返回生成器.而不是之直接執行此函式 函式中包含了yield, 此函式就是生成器函式 大坑: 生成器函式執行之後. 產生一個生成器. 而不是執行函式 def func():     print("我叫周潤發")     yield "林志玲"   # yield表示返回. 不會終止函式的執行     print("寶寶幹嘛去了??")     yield "寶寶回來了"     print("寶寶你在幹嘛?")     # yield "沒了"   ret = func() # 執行函式, 此時沒有執行函式.生成器或者迭代器的好處:節省記憶體 # # 此時我們拿到的是生成器 # print("返回值是", ret) # <generator生成器 object func at 0x0000000009E573B8>   # 執行到下一個yield print(ret.__next__()) # 第一次執行__next__此時函式才開始執行 print(ret.__next__()) # 執行到下一個yield print(ret.__next__()) # StopIteration send()  ----> 同__next__()開始執行 send()可以給上一個yield位置傳值 能夠向下執行的兩個條件:      __next__(),執行到下一個yield      send(),執行到下一個yield,給上一個yield位置傳值, send和__next__()區別:  1. send和next()都是讓⽣成器向下走⼀次  2. send可以給上⼀個yield的位置傳遞值, 不能給最後⼀個yield傳送值. 在第⼀次執⾏⽣ 成器程式碼的時候不能使⽤send() def func():     print("韭菜盒子")     a = yield "韭菜雞蛋"     print("a", a)     b = yield "韭菜西紅柿"     print("b", b)     c = yield "火燒"     yield "GAME OVER"   gen = func()   print(gen.__next__()) # 第一個位置用send沒有任何意義 print(gen.send("籃球")) # 給上一個yield位置傳值  "籃球"這個值賦值給a print(gen.send("足球"))   ##韭菜盒子 韭菜雞蛋 a 籃球 韭菜西紅柿 b 足球 火燒 生成器中記錄的是程式碼而不是函式的執行 def func():             print("我的天哪 ")               yield "寶寶"           gen = func() # 建立生成器.  此時執行會把生成器函式中的程式碼記錄在記憶體         當執行到__next__(), 執行此空間中的程式碼, 執行到yield結束.           優點: 節省記憶體, 生成器本身就是程式碼. 幾乎不佔用記憶體         特點: 惰性機制, 只能向前. 不能反覆 三.各種推導式 列表推導式    [結果 for迴圈 if] #生成列表: python1->python18 lst = [] for i in range(1, 19):     lst.append("python%s期" % i)   print(lst) 列表推導式 [結果 for迴圈 if條件]     lst = ["python%s期" % i for i in range(1, 19)] print(lst)   #生成列表.類表中裝的資料是 1-100之間所有的偶數的平方   lst = [i**2 for i in range(1, 101) if i%2 == 0] print(lst)   #篩選出列表中姓張的同學, lst = ["張無忌", "吳奇隆", "張詩詩", "范冰冰", "張翠山"] lst = ["張無忌", "吳奇隆", "張詩詩", "范冰冰", "張翠山"] lst2 = [name for name in lst if name.startswith("張")] print(lst2)   # 尋找名字中帶有兩個e的人的名字 names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven','Joe'],         ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]   lst = [name for el in names for name in el if name.count("e") == 2] print(lst) 字典推導式    {結果(k:v) for迴圈 if} 字典推導式 語法: { 結果(key:value) for迴圈 if條件} lst = [11,22,33]  # {0:11, 1:22, 2:33}   dic = {i:lst[i] for i in range(len(lst))} print(dic)   練習: {"主食": "炒麵", "副食": "小拌菜", "湯":"疙瘩湯"} 把字典的key和value互換, 生成新字典 dic =  {"主食": "炒麵", "副食": "小拌菜", "湯":"疙瘩湯"} d = { v:k for k, v in dic.items()} print(d) 結合推導式    {結果(k) for迴圈 if} 沒有元組推導式 四.生成器表示式(重點) (結果 for迴圈 if) g = (i for i in range(10)) # 生成器表示式   print(g)  # <generator object <genexpr> at 0x0000000009E573B8>   print(g.__next__()) # 0 print(g.__next__()) # 1 print(g.__next__()) # 2 print(g.__next__()) # 3 print(g.__next__()) # 4 print(g.__next__()) # 5 print(g.__next__()) # 6 print(g.__next__()) # 7 print(g.__next__()) # 8 print(g.__next__()) # 9 # print(g.__next__()) # ??? StopIteration from   可以把一個可迭代物件分別進行yield返回 def func():     lst = ["衣服%s" % i for i in range(500)]     yield from lst # 可以把一個可迭代物件分別進行yield返回       lst1 = ["python%s" % i for i in range(18)]     yield from lst1     gen = func() print(gen.__next__()) print(gen.__next__())