列表解析表達式
先來看一個例子~ Leetcode 171 題
解法很簡單:
sum = 0
for i in range(0, len(s):
sum += 26 ** (len(s) - 1 - i) * (ord(s[i]) - ord("A") + 1)
return sum
那麼,這裏也可以這麼寫。
return sum([26 ** (len(s) - 1 - i) * (ord(s[i]) - ord("A") + 1) for i in range(0, len(s))])
下面的簡寫方法,我們稱作 python的列表解析表達式
。酷酷的 o(╥﹏╥)o有沒有
再來延伸看一下這麼寫的好處(內存佔用)
上代碼:
import timeit
import os
import psutil
# 準備一個5000w 元素的列表 備用
list = range(0, 50000000)
# 計算佔用內存
def show_memory_info(hint):
pid = os.getpid()
p = psutil.Process(pid)
info = p.memory_full_info()
memory = info.uss / 1024. / 1024
print('{} memory used: {} MB'.format(hint, memory))
# 時間
start1 = timeit.default_timer()
# 1.普通方法遍歷元素,append 到新列表
list1 = []
for x in (list):
if x == 20000000:
show_memory_info('1')
if x > 4:
list1.append(x)
show_memory_info('2')
end1 = timeit.default_timer()
print('Running time: {} Seconds'.format(end1 - start1))
start2 = timeit.default_timer()
show_memory_info('3')
# 2. 生成器生成元素到新列表,注意這裏沒有賦值到新列表
(x for x in (list) if x > 4)
show_memory_info('4')
end2 = timeit.default_timer()
print('Running time: {} Seconds'.format(end2 - start2))
運行程序,得到的結果如下:
1 memory used: 783.5625 MB
2 memory used: 1945.28125 MB
Running time: 11.129049652 Seconds
3 memory used: 1945.28125 MB
4 memory used: 1945.28125 MB
Running time: 0.09404864300000071 Seconds
關注幾點:
-
時間上的差別1:
普通遍歷
時間爲9秒,而生成器遍歷
(沒有創建新列表時間爲0.09秒),這個原因在我之前的迭代和生產的對比 博客也寫過了,是因爲只調用了算法 -
時間上的差別2: 如果我把
list1.apped
給刪除了,也就是普通遍歷的append 操作刪除了,時間是 6s 左右 ,看來普通遍歷確實要比生成器佔用更多的內存(廢話),時間也更長 -
時間上的關注點3:如果我把生成器賦值
list2 = (x for x in (list) if x > 4) ,這段代碼的時間是4秒。
可得出,生成器本身生生成元素只是調用了算法,而並未賦值(實際佔用內存) -
內存上的關注點: 同3所說,生成器賦值才產生內存佔用,故而更快。
思考
語法糖其實是迭代的一個延伸,合理的運用不僅可以使代碼變酷,讓別人看不懂,也是可以優化程序運行速度和內存佔用的。