日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python中if的效率_Python 代码性能优化技巧

發(fā)布時間:2024/1/23 python 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python中if的效率_Python 代码性能优化技巧 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

選擇了腳本語言就要忍受其速度,這句話在某種程度上說明了 python 作為腳本的一個不足之處,那就是執(zhí)行效率和性能不夠理想,特別是在 performance 較差的機器上,因此有必要進(jìn)行一定的代碼優(yōu)化來提高程序的執(zhí)行效率。

Python為什么性能差?

1、python是動態(tài)語言

一個變量所指向?qū)ο蟮念愋驮谶\行時才確定,編譯器做不了任何預(yù)測,也就無從優(yōu)化。舉一個簡單的例子: r = a + b?!和b相加,但a和b的類型在運行時才知道,對于加法操作,不同的類型有不同的處理,所以每次運行的時候都會去判斷a和b的類型,然后執(zhí)行對應(yīng)的操作。而在靜態(tài)語言如C++中,編譯的時候就確定了運行時的代碼。

另外一個例子是屬性查找,關(guān)于具體的查找順序在《python屬性查找》中有詳細(xì)介紹。簡而言之,訪問對象的某個屬性是一個非常復(fù)雜的過程,而且通過同一個變量訪問到的python對象還都可能不一樣(參見Lazy property的例子)。而在C語言中,訪問屬性用對象的地址加上屬性的偏移就可以了。

2、python是解釋執(zhí)行

Python不支持JIT(just in time compiler)。雖然大名鼎鼎的google曾經(jīng)嘗試Unladen Swallow 這個項目,但最終也折了。

3、python中一切都是對象

每個對象都需要維護(hù)引用計數(shù),增加了額外的工作。

4、python GIL

GIL是Python最為詬病的一點,因為GIL,python中的多線程并不能真正的并發(fā)。如果是在IO bound的業(yè)務(wù)場景,這個問題并不大,但是在CPU BOUND的場景,這就很致命了。所以筆者在工作中使用python多線程的情況并不多,一般都是使用多進(jìn)程(pre fork),或者在加上協(xié)程。即使在單線程,GIL也會帶來很大的性能影響,因為python每執(zhí)行100個opcode(默認(rèn),可以通過sys.setcheckinterval()設(shè)置)就會嘗試線程的切換,具體的源代碼在ceval.c::PyEval_EvalFrameEx。

5、垃圾回收

這個可能是所有具有垃圾回收的編程語言的通病。python采用標(biāo)記和分代的垃圾回收策略,每次垃圾回收的時候都會中斷正在執(zhí)行的程序,造成所謂的頓卡。infoq上有一篇文章,提到禁用Python的GC機制后,Instagram性能提升了10%。

Python代碼優(yōu)化常用技巧

減小代碼體積

提高代碼的運行效率

一、改進(jìn)算法,選擇合適的數(shù)據(jù)結(jié)構(gòu)(更好的選擇已經(jīng)用藍(lán)色字標(biāo)注出來了)

在算法的時間復(fù)雜度排序上依次是:

O(1) -> O(lg n) -> O(n lg n) -> O(n^2) -> O(n^3) -> O(n^k) -> O(k^n) -> O(n!)

當(dāng)然選擇更合理的算法是最好的優(yōu)化手段,但是在算法沒有辦法更加合理化的時候我們就要選擇更好的數(shù)據(jù)結(jié)構(gòu)。

1、字典(dictionary)與列表(list)

Python 字典中使用了 hash table,因此查找操作的復(fù)雜度為 O(1),而 list 實際是個數(shù)組,在 list 中,查找需要遍歷整個 list,其復(fù)雜度為 O(n),因此對成員的查找訪問等操作字典要比 list 更快。

使用字典會比使用列表效率大概提高一半。

因此在需要多數(shù)據(jù)成員進(jìn)行頻繁的查找或者訪問的時候,使用 dict 而不是 list 是一個較好的選擇。

2、集合(set)和列表(list)

set 的 union, intersection,difference 操作要比 list 的迭代要快。因此如果涉及到求 list 交集,并集或者差的問題可以轉(zhuǎn)換為 set 來操作。(附表一)

表 1. set 常見用法

語法

操作

說明

set(list1) | set(list2)

union

包含 list1 和 list2 所有數(shù)據(jù)的新集合

set(list1) & set(list2)

intersection

包含 list1 和 list2 中共同元素的新集合

set(list1) - set(list2)

difference

在 list1 中出現(xiàn)但不在 list2 中出現(xiàn)的元素的集合

3、對循環(huán)的優(yōu)化

對循環(huán)的優(yōu)化所遵循的原則是盡量減少循環(huán)過程中的計算量,有多重循環(huán)的盡量將內(nèi)層的計算提到上一層。

4、充分利用Lazy if-evaluation 的特性

python 中條件表達(dá)式是 lazy evaluation 的,也就是說如果存在條件表達(dá)式 if x and y,在 x 為 false 的情況下 y 表達(dá)式的值將不再計算。

所以在保證不改變運行結(jié)果的前提下,盡量減少IF里面的條件來提高程序的效率

5、字符串的優(yōu)化

在字符串連接的使用盡量使用 join() 而不是 +;

當(dāng)對字符串可以使用正則表達(dá)式或者內(nèi)置函數(shù)來處理的時候,選擇內(nèi)置函數(shù)。如 str.isalpha(),str.isdigit(),str.startswith(('x', 'yz')),str.endswith(('x', 'yz'));

對字符進(jìn)行格式化比直接串聯(lián)讀取要快,因此要使用

1 out = "%s%s%s%s" % (head, prologue, query, tail)

而不是

1 out = "" + head + prologue + query + tail + ""

6、使用列表解析(list comprehension)和生成器表達(dá)式(generator expression)

列表解析要比在循環(huán)中重新構(gòu)建一個新的 list 更為高效,因此我們可以利用這一特性來提高運行的效率。

1 for i in range (1000000):2   for w inlist:3     total.append(w)

使用列表解析:

1 for i in range (1000000):2   a = [w for w in list]

7、其他優(yōu)化技巧

如果需要交換兩個變量的值使用 a,b=b,a而不是借助中間變量 t=a;a=b;b=t;

在循環(huán)的時候使用 xrange 而不是 range;使用 xrange 可以節(jié)省大量的系統(tǒng)內(nèi)存,因為 xrange() 在序列中每次調(diào)用只產(chǎn)生一個整數(shù)元素。而 range() 將直接返回完整的元素列表,用于循環(huán)時會有不必要的開銷;

使用局部變量,避免"global" 關(guān)鍵字。python 訪問局部變量會比全局變量要快得多;

if done is not None比語句 if done != None 更快;

在耗時較多的循環(huán)中,可以把函數(shù)的調(diào)用改為內(nèi)聯(lián)的方式;

使用級聯(lián)比較 "x < y < z" 而不是 "x < y and y < z";

while 1 要比 while True 更快(當(dāng)然后者的可讀性更好);

build in 函數(shù)通常較快,add(a,b) 要優(yōu)于 a+b。

二、定位程序性能瓶頸

使用 profile 進(jìn)行性能分析

其中 Profiler 是 python 自帶的一組程序,能夠描述程序運行時候的性能,并提供各種統(tǒng)計幫助用戶定位程序的性能瓶頸。

profile 的使用非常簡單,只需要在使用之前進(jìn)行 import 即可。具體實例如下:

1 importprofile2 defprofileTest():3   Total =1;4 for i in range(10):5     Total=Total*(i+1)6 printTotal7 returnTotal8 if __name__ == "__main__":9 profile.run("profileTest()")

程序的運行結(jié)果如下:

其中輸出每列的具體解釋如下:

ncalls:表示函數(shù)調(diào)用的次數(shù);

tottime:表示指定函數(shù)的總的運行時間,除掉函數(shù)中調(diào)用子函數(shù)的運行時間;

percall:(第一個 percall)等于 tottime/ncalls;

cumtime:表示該函數(shù)及其所有子函數(shù)的調(diào)用運行的時間,即函數(shù)開始調(diào)用到返回的時間;

percall:(第二個 percall)即函數(shù)運行一次的平均時間,等于 cumtime/ncalls;

filename:lineno(function):每個函數(shù)調(diào)用的具體信息;

三、Python性能優(yōu)化工具

? Python 性能優(yōu)化除了改進(jìn)算法,選用合適的數(shù)據(jù)結(jié)構(gòu)之外,還有幾種關(guān)鍵的技術(shù),比如將關(guān)鍵 python 代碼部分重寫成 C 擴展模塊,或者選用在性能上更為優(yōu)化的解釋器等,這些在本文中統(tǒng)稱為優(yōu)化工具。python 有很多自帶的優(yōu)化工具,如 Pypy,Cython,Pyrex 等,這些優(yōu)化工具各有千秋,本節(jié)選擇幾種進(jìn)行介紹。

1、Pypy

PyPy 表示 "用 Python 實現(xiàn)的 Python",但實際上它是使用一個稱為 RPython 的 Python 子集實現(xiàn)的,能夠?qū)?Python 代碼轉(zhuǎn)成 C, .NET, Java 等語言和平臺的代碼。PyPy 集成了一種即時 (JIT) 編譯器。和許多編譯器,解釋器不同,它不關(guān)心 Python 代碼的詞法分析和語法樹。 因為它是用 Python 語言寫的,所以它直接利用 Python 語言的 Code Object.。 Code Object 是 Python 字節(jié)碼的表示,也就是說, PyPy 直接分析 Python 代碼所對應(yīng)的字節(jié)碼 ,,這些字節(jié)碼即不是以字符形式也不是以某種二進(jìn)制格式保存在文件中, 而在 Python 運行環(huán)境中。目前版本是 1.8. 支持不同的平臺安裝,windows 上安裝 Pypy 需要先下載 ,然后解壓到相關(guān)的目錄,并將解壓后的路徑添加到環(huán)境變量 path 中即可。

接下來我們來測試一下使用同一個程序python解釋器和pypy解釋器的編譯時間為多少?到底有沒有提升速度?

1 importtime2

3 t =time.time()4 for i in range(10 ** 8):5 continue

6 print(time.time() - t)

我們可以看到這是python解釋器的編譯時間:

下面這是pypy解釋器的編譯時間:

從上面對比我們發(fā)現(xiàn)python解釋器的編譯時間為:5.84,

而pypy解釋器的編譯時間為0.32,

從編譯時間上我們可以看出速度提升了將近22倍!!

2、Cython

Cython 是用 python 實現(xiàn)的一種語言,可以用來寫 python 擴展,用它寫出來的庫都可以通過 import 來載入,性能上比 python 的快。cython 里可以載入 python 擴展 ( 比如 import math),也可以載入 c 的庫的頭文件 ( 比如 :cdef extern from "math.h"),另外也可以用它來寫 python 代碼。將關(guān)鍵部分重寫成 C 擴展模塊

Linux Cpython 的安裝可以參考文檔

Cython 代碼與 python 不同,必須先編譯,編譯一般需要經(jīng)過兩個階段,將 pyx 文件編譯為 .c 文件,再將 .c 文件編譯為 .so 文件。編譯有多種方法:

通過命令行編譯

使用 distutils 編譯

下面來進(jìn)行一個簡單的性能比較:

1 from time importtime2 deftest(int n):3 cdef int a =04 cdef int i5 for i inxrange(n):6 a+=i7 returna8

9 t =time()10 test(10000000)11 print "total run time:"

12 print time()-t

測試結(jié)果:

[GCC 4.0.2 20051125 (Red Hat 4.0.2-8)] on linux2

Type"help", "copyright", "credits" or "license" formore information.>>> importpyximport; pyximport.install()>>> importctest

total run time:0.00714015960693

使用python測試結(jié)果:

通過清楚地對比可以發(fā)現(xiàn)使用 Cython 的速度提升了100多倍。

總結(jié)

以上是生活随笔為你收集整理的python中if的效率_Python 代码性能优化技巧的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。