推導式與生成器
阿新 • • 發佈:2020-12-08
一、列表推導式
'''通過一行迴圈判斷,遍歷一系資料的方式'''
推導式語法 val for val in Iterable 三種方式: [val for val in Iterable] {val for val in Iterable} {k:v for k,v in Iterable}
1、向列表裡插入100條資料
#列表裡面需要100條資料 lst = [] for i in range(1,101): lst.append(i) print(lst)
改為推導式
# 基本語法 lst = [i for i in range(1,101)] print(lst)
2、[1,2,3,4,5] -> [3,6,9,12,15]
lst = [1,2,3,4,5] lst_new = [] for i in lst: res = i * 3 lst_new.append(res) print(lst_new)
改成推導式
lst = [i*3 for i in lst] print(lst)
3、帶有判斷條件的單迴圈推導式 (只能是單項分支,接在for後面)
lst = [1,2,3,4,5,6,7,8] lst_new= [] for i in lst: if i %2 ==1: lst_new.append(i) print(lst_new )
改寫成推導式
lst = [i for i in lst if i %2 ==1] print(lst)
4、雙迴圈推導式
lst1 = ["李博倫","高雲峰","孫致和","葛龍"] lst2 = ["李亞","劉彩霞","劉子豪","劉昕"] # "誰"❤"誰" lst_new = [] for i in lst1: for j in lst2: strvar = i+ '*' + j lst_new.append(strvar)print(lst_new)
改寫成推導式
# 改寫成推導式 lst = [i+'*'+j for i in lst1 for j in lst2] print(lst)
5、帶有判斷條件的多迴圈推導式
lst_new = [] for i in lst1: for j in lst2: if lst1.index(i) == lst2.index(j) strvar = i + '*' + j lst_new.append(strvar) print(lst_new)
改寫成推導式
lst = [ i + "❤" + j for i in lst1 for j in lst2 if lst1.index(i) == lst2.index(j) ] print(lst)
二、集合推導式
""" 案例: 滿足年齡在18到21,存款大於等於5000 小於等於5500的人, 開卡格式為:尊貴VIP卡老x(姓氏),否則開卡格式為:摳腳大漢卡老x(姓氏) 把開卡的種類統計出來 """
listvar = [ {"name":"劉鑫煒","age":18,"money":10000}, {"name":"劉聰","age":19,"money":5100}, {"name":"劉子豪","age":20,"money":4800}, {"name":"孔祥群","age":21,"money":2000}, {"name":"宋雲傑","age":18,"money":20} ]
常規寫法
setvar = set() for i in listvar: if 18 <= i["age"] <= 21 and 5000 <= i["money"] <= 5500: res = "尊貴VIP卡老" + i["name"][0] else: res = "摳腳大漢卡老" + i["name"][0] setvar.add(res) print(setvar)
改寫成集合推導式
# {三元運算子 + 推導式} setvar = { "尊貴VIP卡老" + i["name"][0] if 18 <= i["age"] <= 21 and 5000 <= i["money"] <= 5500 else "摳腳大漢卡老" + i["name"][0] for i in listvar } print(setvar)
三、字典推導式
""" enumerate(iterable,[start=0]) 功能:列舉 ; 將索引號和iterable中的值,一個一個拿出來配對組成元組放入迭代器中 引數: iterable: 可迭代性資料 (常用:迭代器,容器型別資料,可迭代物件range) start: 可以選擇開始的索引號(預設從0開始索引) 返回值:迭代器 """
from collections import Iterator lst = ["東邪","西毒","南帝","北丐"] # 基本使用 it = enumerate(lst) print(isinstance(it,Iterator))
for + next
# for + next for i in range(4): print(next(it)) # (0, '東邪') # (1, '西毒') # (2, '南帝') # (3, '北丐')
list
"""start可以指定開始值,預設是0""" it = enumerate(lst,start=1) print(list(it)) #[(1, '東邪'), (2, '西毒'), (3, '南帝'), (4, '北丐')]
enumerate 形成字典推導式 變成字典
dic = { k:v for k,v in enumerate(lst,start=1) } print(dic) # {1: '東邪', 2: '西毒', 3: '南帝', 4: '北丐'}
dict 強制變成字典
dic = dict(enumerate(lst,start=1)) print(dic) # {1: '東邪', 2: '西毒', 3: '南帝', 4: '北丐'}
四、zip
""" zip(iterable, ... ...) 功能: 將多個iterable中的值,一個一個拿出來配對組成元組放入迭代器中 iterable: 可迭代性資料 (常用:迭代器,容器型別資料,可迭代物件range) 返回: 迭代器 特徵: 如果找不到對應配對的元素,當前元素會被捨棄 """
# 基本使用 lst1 = ["晏國彰","劉子濤","郭凱","宋雲傑"] lst2 = ["劉有右柳翔","馮雍","孫志新"] lst3 = ["周鵬飛","袁偉倬"] # it = zip(lst1,lst2) it = zip(lst1,lst2,lst3) print(isinstance(it,Iterator)) print(list(it)) """ [('晏國彰', '劉有右柳翔'), ('劉子濤', '馮雍'), ('郭凱', '孫志新')] [('晏國彰', '劉有右柳翔', '周鵬飛'), ('劉子濤', '馮雍', '袁偉倬')] """
1、zip 形成字典推導式 變成字典
lst1 = ["晏國彰","劉子濤","郭凱","宋雲傑"] lst2 = ["劉有右柳翔","馮雍","孫志新"] dic = { k:v for k,v in zip(lst1,lst2) } print(dic) # dict 強制變成字典 dic = dict(zip(lst1,lst2)) print(dic)
五、生成器表示式
""" #生成器本質是迭代器,允許自定義邏輯的迭代器 #迭代器和生成器區別: 迭代器本身是系統內建的.重寫不了.而生成器是使用者自定義的,可以重寫迭代邏輯 #生成器可以用兩種方式建立: (1)生成器表示式 (裡面是推導式,外面用圓括號) (2)生成器函式 (用def定義,裡面含有yield) """
from collections import Iterator,Iterable # 生成器表示式 gen = (i*2 for i in range(1,11)) print(isinstance(gen,Iterator)) # next res = next(gen) print(res) # for for i in gen: print(i) # for + next gen = (i*2 for i in range(1,11)) for i in range(3): res = next(gen) print(res) # list print("<=====>") res = list(gen) print(res)
六、生成器函式
""" # yield 類似於 return 共同點在於:執行到這句話都會把值返回出去 不同點在於:yield每次返回時,會記住上次離開時執行的位置 , 下次在呼叫生成器 , 會從上次執行的位置往下走 而return直接終止函式,每次重頭呼叫. yield 6 和 yield(6) 2種寫法都可以 yield 6 更像 return 6 的寫法 推薦使用 """
1、生成器函式的基本語法
# 定義一個生成器函式 def mygen(): print(111) yield 1 print(222) yield 2 print(333) yield 3 # 初始化生成器函式,返回生成器物件,簡稱生成器 gen = mygen() print(isinstance(gen,Iterator)) # 使用next呼叫 res = next(gen) print(res) res = next(gen) print(res) res = next(gen) print(res) # res = next(gen) error # print(res)
2、程式碼優化
def mygen(): for i in range(1,101): yield "該球衣號碼是{}".format(i) # 初始化生成器函式 -> 生成器 gen = mygen() # for + next 呼叫資料 for i in range(50): res = next(gen) print(res) print("<====>") for i in range(30): res = next(gen) print(res)
3、send用法\
""" ### send # next和send區別: next 只能取值 send 不但能取值,還能傳送值 # send注意點: 第一個 send 不能給 yield 傳值 預設只能寫None 最後一個yield 接受不到send的傳送值 send 是給上一個yield傳送值 """
def mygen(): print("process start") res = yield 100 print(res,"內部列印1") res = yield 200 print(res,"內部列印2") res = yield 300 print(res,"內部列印3") print("process end") # 初始化生成器函式 -> 生成器 gen = mygen() # 在使用send時,第一次呼叫必須傳遞的引數是None(硬性語法),因為第一次還沒有遇到上一個yield '''第一次呼叫''' res = gen.send(None) #<=> next(gen) print(res) '''第二次呼叫''' res = gen.send(101) #<=> next(gen) print(res) '''第三次呼叫''' res = gen.send(201) #<=> next(gen) print(res) '''第四次呼叫, 因為沒有更多的yield返回資料了,所以StopIteration'''
4、yield from : 將一個可迭代物件變成一個迭代器返回
def mygen(): yield from ["馬生平","劉彩霞","餘銳","晏國彰"] gen = mygen() print(next(gen)) print(next(gen)) print(next(gen)) print(next(gen))
5、用生成器描述斐波那契數列
"""1 1 2 3 5 8 13 21 34 ... """ """ yield 1 a,b = b,a+b = 1,1 yield 1 a,b = b,a+b = 1,2 yield 2 a,b = b,a+b = 2,3 yield 3 a,b = b,a+b = 3,5 yield 5 .... """ def mygen(maxlen): a,b = 0,1 i = 0 while i < maxlen: yield b a,b = b,a+b i+=1 # 初始化生成器函式 -> 生成器 gen = mygen(10) for i in range(3): print(next(gen))