前言
python的生成式在一些類型相互轉換的時候可以寫出十分優雅的代碼,如列表轉換成另一個列表、字典、或元組,並且代碼的執行效率也比使用for...in...循環高。
系列文章
列表生成式
列表生成式即生成列表的生成式,寫法簡單而優雅,可以將多行代碼融合成一行。主要的作用是將其他對象轉換成列表或對原來的列表進行過濾。
列表生成式的代碼效率是高於多行循環結構的,原因是將原本多行代碼融合一行,解釋加快。
# 列表轉換列表
ls = [1,2,4,6]
ls1 = [x**2 for x in ls]
print(ls1)
結果:[1,4,16,36]
# 也可以這樣
list(x**2 for x in range(10))
# 對列表過濾,返回true的才會保留到列表
ls = [1,2,4,6]
ls1 = [x**2 for x in ls if x > 3]
print(ls1)
結果:[16, 36]
# 多條件過濾
ls = [1,2,4,6]
ls1 = [x**2 if x > 2 else x**3 for x in ls]
print(ls1)
結果:[1, 8, 16, 36]
# 多重循環
ls = [1,2,4,6]
ls1 = [x**y if x > 2 else x**3 for x in ls for y in ls]
print(ls1)
結果:[1, 1, 1, 1, 8, 8, 8, 8, 4, 16, 256, 4096, 6, 36, 1296, 46656]
生成器生成式
在涉及到需要遍歷列表而不是針對列表的某個值操作時,使用生成器代替列表可以減少內存的消耗。
ls = [1,2,4,6]
ls1 = (x**2 for x in ls)
print(ls1)
結果:<generator object <genexpr> at 0x0000021B21DED150>
# 當然我們也可以這樣
def gener(l):
for x in l:
yield x**2
# 只不過定義結構偏重型,當操作復雜的時候才采用
# 通過for..in取數據不需要處理StopIteration
for i in ls1:
pass
# next()方法需要處理StopIteration
while True:
try:
print(next(ls1))
except StopIteration:
pass
字典生成式
字典生成式在一些需要列表或元組轉化成字典的場合可以寫出很優雅的代碼。
# dict()可以接受類似列表生成式的寫法,前提是ls至少是二維可迭代對象,否則報錯
ls = [('name1','xiao'),('name2','wang')]
dict_ls = dict(x for x in ls)
print(dict_ls)
結果:{'name1': 'xiao', 'name2': 'wang'}
# 也可以針對zip使用
d = dict(zip([1,2],[3,4,]))
print(d)
# 結果
{1: 3, 2: 4}
# 直接和列表生成式相似的寫法
d = {x:y for x,y in enumerate(range(10))}
集合生成式
按照列表生成式類似的寫法我們可以寫集合生成式。
print(set(i for i in range(5)))
print({i for i in range(5)})
print(frozenset(i for i in range(5)))
# 結果
{0, 1, 2, 3, 4}
{0, 1, 2, 3, 4}
frozenset({0, 1, 2, 3, 4})
元組生成式
由於()這個類似列表生成式的形式被生成器占用了,所有元組生成式使用tuple()來進行。
ls = [('name1',['1','2']),('name2','wang')]
dict_ls = tuple(x for x in ls)
print(dict_ls)
結果:(('name1', ['1', '2']), ('name2', 'wang'))
條件表達式代碼壓縮
對於一些如果代碼不算長的if...else...的判斷情況,可以將代碼寫在一行,顯得非常的優雅。
x = 1 if 1>0 else None
