python 生成器 和生成器函式 以及各種推導式
阿新 • • 發佈: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__())