5個(gè)手到擒來的Python提速技巧

在工作中,我們常常面臨著代碼提速優(yōu)化問題,本文就為大家介紹幾種Python常用的提速技巧。
優(yōu)化原則:
1.先保證代碼可以正確運(yùn)行,再進(jìn)行性能優(yōu)化
2.優(yōu)化的選擇通常是犧牲空間換取時(shí)間,所有我們需要權(quán)衡代價(jià)
3.著重優(yōu)化代碼耗時(shí)的部分,通篇優(yōu)化通常會(huì)降低代碼的可讀性
0 定義耗時(shí)裝飾器
#?可監(jiān)控程序運(yùn)行時(shí)間
import?time
def?clock(func):
????def?wrapper(*args,?**kwargs):
????????start_time?=?time.time()
????????result?=?func(*args,?**kwargs)
????????end_time?=?time.time()
????????print("共耗時(shí):?%s秒"?%?round(end_time?-?start_time,?2))
????????return?result
????return?wrapper
1 避免使用全局變量
start_time?=?time.time()
size?=?10000
for?x?in?range(size):
????for?y?in?range(size):
????????z?=?x?*?y
end_time?=?time.time()
print('共耗時(shí):%s秒'?%?round(end_time?-?start_time,?2))
#?共耗時(shí):11.78秒,不推薦
#?使用局部變量
@clock
def?multiplication():
????size?=?10000
????for?x?in?range(size):
????????for?y?in?range(size):
????????????z?=?x?*?y
multiplication()
#?共耗時(shí):?5.5秒,提速50%
2 避免訪問方法(函數(shù))的屬性,盡量使用from X import X
import?math
@clock
def?computeSqrt():
????result?=?[]
????for?i?in?range(10000000):
????????#?math方法訪問sqrt屬性
????????result.append(math.sqrt(i))
computeSqrt()
#?不推薦,共耗時(shí):?2.09秒
#?使用from?X?import?X,直接訪問sqrt
from?math?import?sqrt
@clock
def?computeSqrt():
????result?=?[]
????for?i?in?range(10000000):
????????result.append(sqrt(i))
computeSqrt()
#?推薦,共耗時(shí):?1.75秒
在【1】中我們講到,局部變量的查找會(huì)比全局變量更快,因此對(duì)于頻繁訪問的變量append,通過將其改為局部變量可以加速運(yùn)行。
from?math?import?sqrt
@clock
def?computeSqrt():
????result?=?[]
????#?賦值給局部變量
????append?=?result.append
????for?i?in?range(10000000):
????????append(sqrt(i))
computeSqrt()
#?推薦,共耗時(shí):?1.45秒
3 遍歷優(yōu)化
#?使用while進(jìn)行遍歷
@clock
def?circulate():
????i?=?0
????li?=?[]
????append?=?li.append
????while?i?10000000:
????????append(i*2)
????????i?+=?1
????return?li
circulate()
#?不推薦,共耗時(shí):1.48秒
@clock
def?circulate():
????li?=?[]
????append?=?li.append
????#?使用for代替while
????for?i?in?range(10000000):
????????append(i*2)
????return?li
circulate()
#?for優(yōu)于while,共耗時(shí):1.09秒
@clock
def?circulate():
????#?使用列表推導(dǎo)式
????return?[i*2?for?i?in?range(10000000)]
circulate()
#?推薦列表推導(dǎo)式,共耗時(shí):0.88秒。但不適用于復(fù)雜計(jì)算。
4 減少內(nèi)層for循環(huán)的計(jì)算
from?math?import?sqrt
@clock
def?inner():
????size?=?10000
????for?x?in?range(size):
????????for?y?in?range(size):
????????????#?相當(dāng)于在重復(fù)計(jì)算sqrt(x)
????????????z?=?sqrt(x)?+?sqrt(y)
inner()?
#?不推薦,共耗時(shí):19.00秒
from??math?import?sqrt
@clock
def?inner():
????size?=?10000
????for?x?in?range(size):
????????#?只計(jì)算一次sqrt(x),然后將它存了起來
????????sqrt_x?=?sqrt(x)
????????for?y?in?range(size):
????????????z?=?sqrt_x?+?sqrt(y)
inner()?
#?推薦,共耗時(shí):10.22秒
5 使用Numpy數(shù)據(jù)類型進(jìn)行運(yùn)算
因?yàn)?code style="padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(200, 54, 6);font-size: 13px;">Numpy底層是用C語言實(shí)現(xiàn)的,而Python這種腳本語言相比C/C++這種編譯語言在效率和性能方面有天然劣勢,所以我們可以引入Numpy包,對(duì)數(shù)據(jù)進(jìn)行類型轉(zhuǎn)換后再進(jìn)行計(jì)算。
import?numpy?as?np
li?=?[i?for?i?in?range(10000000)]
@clock
def?npSpeed():
????#?使用Python方法
????sum(li)
npSpeed()?
#?共耗時(shí)0.79秒
import?numpy?as?np
li?=?np.array([i?for?i?in?range(100000000)])
@clock
def?npSpeed():
????#?使用Numpy方法
????np.sum(li)
npSpeed()?
#?共耗時(shí)0.11秒,速度約是Python的8倍
Numpy的優(yōu)勢在數(shù)據(jù)量越大時(shí),體現(xiàn)的也會(huì)更加明顯。所以在機(jī)器學(xué)習(xí)與深度學(xué)習(xí)項(xiàng)目任務(wù)中,Numpy的使用就非常頻繁。
3、爆強(qiáng)!直接把 Python 編寫的圖形程序打包為安卓 APP
5、Windows重要功能被閹割,全球用戶怒噴數(shù)月后微軟終于悔改

