一、列表推導式
列表推導式、字典推導式、集合推導式
舊的列表 ——> 新的列表
1、列表推導式
格式: [表達式 for 變量 in 舊列表] 或者 [表達式 for 變量 in 舊列表 if 條件]
#過濾掉長度小於等於3的姓名
names = ['aaa', 'bbbb', 'jack', 'abc']
result = [name for name in names if len(name) > 3]
print(result)
#將過濾的姓名首字母大寫
result = [name.capitalize() for name in names if len(name) > 3]
print(result)
'''
簡化了此過程
for name in names:
newlist = []
if len(name) > 3:
name.title()
newlist.append(name)
return newlist
'''
#將1~100之間能被3整除,組成一個新的列表
newlist = [i for i in range(1, 101) if i % 3 == 0 and i % 5 == 0]#攜帶if條件
print(newlist)
#此處,類比三元表達式 條件爲真時的結果 if 條件 else 條件爲假時的結果
# 列表推導式 [表達式 for i in 列表 if 條件]
#[(偶數, 奇數), (), ()] 0~5的偶數 0~10的奇數
newlist = [(x, y) for x in range(5) if x % 2 == 0 for y in range(10) if y % 2 != 0]
print(newlist)
'''
def func():
newlist = []
for i in range(5):#偶數
if i % 2 == 0:
for j in range(10):
if j % 2 != 0:
newlist.append((i, j))
return newlist
result = func()
print(result)
'''
#list1 = [[1, 2, 3], [4, 5, 6], [7 ,8, 9], [1, 3, 5]] --->[3, 6, 9 ,5]
list1 = [[1, 2, 3], [4, 5, 6], [7 ,8, 9], [1, 3, 5]]
newlist = [i[-1] for i in list1]#沒有條件 #取每個列表中最後一個元素
print(newlist)
dict1 = {'name' : 'tom', 'salary' : 5000}
dict2 = {'name' : 'lucy', 'salary' : 8000}
dict3 = {'name' : 'jack', 'salary' : 4500}
dict4 = {'name' : 'lily', 'salary' : 3000}
list1 = [dict1, dict2, dict3, dict4]
#if 薪資大於 5000, 加200, 低於5000 加500
#if爲true執行語句 if 條件 else 執行語句 for 元素 in 列表
newlist = [person['salary'] + 200 if person['salary'] > 5000 else person['salary'] + 500 for person in list1]
print(newlist)
2、集合推導式 {}
集合去重且無順序 類似列表推導式,在列表推導式的基礎上添加了一個去除重複項
list1 = [1, 5, 35, 3, 5, 1]
set1 = {x - 1 for x in list1 if x > 5}
print(set1)
3、字典推導式
#字典推導式
#key與value進行交換
dict1 = {'a' : 'A', 'b' : 'B', 'c' : 'C', 'd' : 'C'}
newdict = {value : key for key, value in dict1.items()}
print(newdict)
二、生成器 generator
通過列表生成式(列表推導式),我們可以直接創建一個列表,但是受到內存限制,列表容量肯定是有限的。
而且,創建一個包含100萬個元素的列表,不僅佔用很大的存儲空間。
如果我們僅僅需要訪問前面幾個元素,那後面絕大多數元素佔用的空間都白白浪費了。
所以,如果列表元素可以按照某種算法推算出來,那我們是否可以在循環的過程中不斷推算出後續的元素呢?
這樣就不必創建完成的list,從而節省大量的空間。
在Python中,這種一邊循環一邊計算的機制,稱爲生成器:generator
得到生成器的方式:
方式一、通過列表推導式得到生成器
#得到列表[0, 3, 6, 9, 12, ..., 30]
newlist = [x * 3 for x in range(11)]
print(type(newlist)) #list
#得到生成器 將列表推導式外部[] 改爲 ()
g = (x * 3 for x in range(11))
print(type(g)) #generator
print(g) #<generator object <genexpr> at 0x0000000001D6FA20>
#方式1:通過調用 __next__()
print(g.__next__()) #0
print(g.__next__()) #3 只有調用時,才產生
#方式2: next(生成器對象) built-in系統內置函數
#每調用一次next(),則會產生一個元素
print(next(g)) #6
print(next(g)) #9
# StopIteration 生成器本來可以生成10個,現在得到了10個,如果繼續調用next(生成器) 會拋出異常
while True:
try:
e = next(g)
print(e)
except:
print("沒有更多的元素")
break
方式二、藉助函數完成 yield
函數中出現 yield,說明函數已經不是函數,而是生成器
步驟:
1、定義一個函數,函數中使用yield關鍵字
2、調用函數,接收調用的結果
3、得到的結果就是生成器
4、藉助於next(生成器) 或 __next__() 得到元素
def func1():
n = 0
while True:
n += 1
yield n # return n + 暫停
g = func1()
print(g) #generator
print(next(g)) # 1
print(next(g)) # 2
#裴波那切數列 0、1、1、2、3、5、8、13、21、34、55、89、144...
def fib(length):
a, b = 0, 1
n = 0
while n < length:
yield b #return b + 暫停
a, b = b, a + b #再次調用,在yield 下方執行代碼
n += 1
return '沒有更多元素!' #--->就是在得到StopIteration後提示信息
g = fib(8)
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
生成器的方法:
__next__(): 獲取下一個元素
send(value): 向每次生成器調用中傳值 注意:第一次需要調用send(None)
生成器send(value) 方法:
def gen():
i = 0
while i < 5:
temp = yield i #return i + pause
print('temp', temp)
i += 1
return '沒有更多的數據'
g = gen()
n1 = g.send(None)
n1 = g.send("test")
print(n1)
n2 = g.send("aaa")
print(n2)
三、進程、線程、協程之間的關係
進程 包含多個 線程 包含多個 協程
例如:迅雷下載,同時10個線程
#一個進程可以開啓多個協程
def task1(n):
for i in range(n):
print("正在搬第{}塊磚".format(i))
yield None
def task2(n):
for i in range(n):
print("正在聽第{}首歌".format(i))
yield None
#未添加生成器,先搬磚,後聽歌,無法交替進行 添加生成器可以交替完成
g1 = task1(10)
g2 = task2(6)
while True:
try:
g1.__next__()
g2.__next__()
except:
pass
四、總結生成器 generator
定義生成器的方式:
1、通過列表推導式構建
g = (x + 1 for x in range(10))
2、函數和yield
def func():
...
yield
g = func()
產生元素:
1、next(generator) --->每次調用都會產生一個新的元素,如果元素產生完畢,再次調用的話就會產生異常
2、生成器內置方法:
g.__next__()
g.send(value)
應用:協程
五、可迭代的 和 迭代器
可迭代的:
可迭代的對象: 1、生成器 2、元組、列表、集合、字典、字符串
如何判斷一個對象是否是可迭代的?
from collections import Iterable
isinstance(list1, Iterable)
迭代器:
迭代是訪問集合元素的一種方式,迭代器是一個可以記住遍歷的位置的對象。
特點:
1、迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。
2、迭代器只能往前不會後退。
3、可以被next()函數調用並不斷返回下一個值的對象稱爲迭代器:Iterator
可迭代的 是否是 迭代器?
生成器是可迭代的,是迭代器
list是可迭代的,但不是迭代器
list ---> iter(list) ---> 迭代器 next()
from collections import Iterable
list1 = [1, 3, 5]
f = isinstance(list1, Iterable)
print(f)
f = isinstance('abc', Iterable)
print(f)
f = isinstance(100, Iterable)
print(f)
g = (x for x in range(10))
f = isinstance(g, Iterable)
print(f)
#list ---> 迭代器 通過iter() 函數可迭代的變成一個迭代器
list1 = [1, 3, 45, 9, 6]
i_list1 = iter(list1)
print(next(i_list1))
print(next(i_list1))
六、生成器和迭代器的關係
迭代器:可以調用next(generator)
迭代器:包含生成器
迭代器分爲兩大類:1、生成器是迭代器的一種
2、藉助iter() 函數的轉換,轉換成迭代器
例如:iter(list) iter(tuple)
七、總結
列表推導式:
[表達式 for 變量 in 列表]
[x+2 for x in list1] ---> 新的列表
1、[表達式 for 變量 in 列表 if 條件]
[x+2 for x in list1 if x % 2 == 0]
2、[結果A if 條件 else 結果B for x in list1]
[x+2 if x % 2 == 0 else x + 1 for x in list1]
集合推導式: {表達式 for i in 列表} --->類似列表推導式,但是沒有重複元素
字典推導式: {key, value for k, v in 字典.items()}
生成器:generator
1、使用類似的列表推導式 g = (表達式 for 變量 in 列表)
此時的g就是生成器
2、函數+yield
def func():
...
yield
...
g = func()
得到裏面的元素:
系統函數: next(g)
生成器內置函數: __next__(), [send(None), send(value)]
可迭代的與迭代器:
可迭代:1、生成器 2、字符串、列表、集合、元組
Iterable
isinstance(x, Iterable) --->true, false
迭代器:調用next(g)
生成器就是一個迭代器 --->next(g) --->下一個元素
next(list) ---> iter(list) ---> next(iter(list)) --->下一個元素