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

small_caier發表於2018-12-11
一.生成器
   本質就是迭代器. 我們可以直接執⾏__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__())

相關文章