python提升
『壹』 提升python運行速度的5個小技巧
pre{overflow-x: auto}Python 是世界上使用最廣泛的編程語言之一。它是一種解釋型高級通用編程語言,具有廣泛的用途,幾乎可以將其用於所有事物。其以簡單的語法、優雅的代碼和豐富的第三方庫而聞名。python除了有很多優點外,但在速度上還有一個非常大的缺點。
雖然Python代碼運行緩慢,但可以通過下面分享的5個小技巧提升Python運行速度!
首先,定義一個計時函數timeshow,通過簡單的裝飾,可以列印指定函數的運行時間。
這個函數在下面的例子中會被多次使用。
def timeshow(func): from time import time def newfunc(*arg, **kw): t1 = time() res = func(*arg, **kw) t2 = time() print(f"{func.__name__: >10} : {t2-t1:.6f} sec") return res return newfunc @timeshow def test_it(): print("hello pytip") test_it() 1. 選擇合適的數據結構使用正確的數據結構對python腳本的運行時間有顯著影響。Python 有四種內置的數據結構:
列表 : List
元組 : Tuple
集合 : Set
字典 : Dictionary
但是,大多數開發人員在所有情況下都使用列表。這是不正確的做法,應該根據任務使用合適數據結構。
運行下面的代碼,可以看到元組執行簡單檢索操作的速度比列錶快。其中dis模塊反匯編了一個函數的位元組碼,這有利於查看列表和元組之間的區別。
import dis def a(): data = [1, 2, 3, 4, 5,6,7,8,9,10] x =data[5] return x def b(): data = (1, 2, 3, 4, 5,6,7,8,9,10) x =data[5] return x print("-----:使用列表的機器碼:------") dis.dis(a) print("-----:使用元組的機器碼:------") dis.dis(b)運行輸出:
-----:使用列表的機器碼:------
3 0 LOAD_CONST 1 (1)
2 LOAD_CONST 2 (2)
4 LOAD_CONST 3 (3)
6 LOAD_CONST 4 (4)
8 LOAD_CONST 5 (5)
10 LOAD_CONST 6 (6)
12 LOAD_CONST 7 (7)
14 LOAD_CONST 8 (8)
16 LOAD_CONST 9 (9)
18 LOAD_CONST 10 (10)
20 BUILD_LIST 10
22 STORE_FAST 0 (data)
4 24 LOAD_FAST 0 (data)
26 LOAD_CONST 5 (5)
28 BINARY_SUBSCR
30 STORE_FAST 1 (x)
5 32 LOAD_FAST 1 (x)
34 RETURN_VALUE
-----:使用元組的機器碼:------
7 0 LOAD_CONST 1 ((1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
2 STORE_FAST 0 (data)
8 4 LOAD_FAST 0 (data)
6 LOAD_CONST 2 (5)
8 BINARY_SUBSCR
10 STORE_FAST 1 (x)
9 12 LOAD_FAST 1 (x)
14 RETURN_VALUE
看下列表的機器碼,冗長而多餘!
2. 善用強大的內置函數和第三方庫如果你正在使用python並且仍在自己編寫一些通用函數(比如加法、減法),那麼是在侮辱python。 Python有大量的庫和內置函數來幫助你不用編寫這些函數。 如果研究下,那麼你會驚奇地發現幾乎90%的問題已經有第三方包或內置函數來解決。
可以通過訪問官方文檔查看所有內置函數。你也可以在wiki python上找到更多使用內置函數的場景。
比如,現在我們想合並列表中的所有單詞為一個句子,比較法自己編寫和調用庫函數的區別:
# ❌ 正常人能想到的方法 @timeshow def f1(list): s ="" for substring in list: s += substring return s # ✅ pythonic 的方法 @timeshow def f2(list): s = "".join(list) return s l = ["I", "Love", "Python"] * 1000 # 為了看到差異,我們把這個列表放大了 f1(l) f2(l)運行輸出:
f1 : 0.000227 sec
f2 : 0.000031 sec
3. 少用循環
用 列表推導式 代替循環
用 迭代器 代替循環
用 filter() 代替循環
減少循環次數,精確控制,不浪費CPU
## 返回n以內的可以被7整除的所有數字。 # ❌ 正常人能想到的方法: @timeshow def f_loop(n): L=[] for i in range(n): if i % 7 ==0: L.append(i) return L # ✅ 列表推導式 @timeshow def f_list(n): L = [i for i in range(n) if i % 7 == 0] return L # ✅ 迭代器 @timeshow def f_iter(n): L = (i for i in range(n) if i % 7 == 0) return L # ✅ 過濾器 @timeshow def f_filter(n): L = filter(lambda x: x % 7 == 0, range(n)) return L # ✅ 精確控制循環次數 @timeshow def f_mind(n): L = (i*7 for i in range(n//7)) return L n = 1_000_000 f_loop(n) f_list(n) f_iter(n) f_filter(n) f_mind(n)輸出為:
f_loop : 0.083017 sec
f_list : 0.056110 sec
f_iter : 0.000015 sec
f_filter : 0.000003 sec
f_mind : 0.000002 sec
誰快誰慢,一眼便知!
filter 配合 lambda 大法就是屌!!!
4. 避免循環重復計算如果你有一個迭代器,必須用它的元素做一些耗時計算,比如匹配正則表達式。你應該將正則表達式模式定義在循環之外,因為最好只編譯一次模式,而不是在循環的每次迭代中一次又一次地編譯它。
只要有可能,就應該嘗試在循環外進行盡可能多的運算,比如將函數計算分配給局部變數,然後在函數中使用它。
# ❌ 應改避免的方式: @timeshow def f_more(s): import re for i in s: m = re.search(r'a*[a-z]?c', i) # ✅ 更好的方式: @timeshow def f_less(s): import re regex = re.compile(r'a*[a-z]?c') for i in s: m = regex.search(i) s = ["abctestabc"] * 1_000 f_more(s) f_less(s)輸出為:
f_more : 0.001068 sec
f_less : 0.000365 sec
內存佔用是指程序運行時使用的內存量。為了讓Python代碼運行得更快,應該減少程序的內存使用量,即盡量減少變數或對象的數量。
Python 訪問局部變數比全局變數更有效。在有必要之前,應該始終嘗試忽略聲明全局變數。一個在程序中定義過的全局變數會一直存在,直到整個程序編譯完成,所以它一直占據著內存空間。另一方面,局部變數訪問更快,且函數完成後即可回收。因此,使用多個局部變數比使用全局變數會更好。
# ❌ 應該避免的方式: message = "Line1 " message += "Line2 " message += "Line3 " # ✅ 更好的方式: l = ["Line1","Line2","Line3"] message = ' '.join(l) # ❌ 應該避免的方式: x = 5 y = 6 def add(): return x+y add() # ✅ 更好的方式: def add(): x = 5 y = 6 return x+y add()總結
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注的更多內容!
『貳』 想學Python提升自己,應該先從什麼開始
【導讀】最近無論是刷微信還是刷抖音,都會彈出很多關於Python是資訊信息,老實說,Python真是是一個非常好用的數據處理工具,學會Python可以幫助你更加高效的處理一些工作或者學習上的數據,那麼想學Python提升自己,應該先從什麼開始?小編其實很多時候,語言學習重要的不是方法,而是心態。心態擺正了,才有堅持學習下去的動力。
是什麼促使我開始學習Python?
剛開始接觸Python只懂得它適合做很多自動化腳本。然後在技術論壇去下載別人的Python小程序,令我印象最深刻的是籃球比分板的小插件。我在公司上班的時候沒法看NBA,這個小插件會在電腦屏幕右上方實時顯示雙方隊伍的比分情況,就這樣,我靠著這個小插件看完了整個NBA季後賽。
雖然只有數字,但球粉們都懂,在沒法看球賽的環境下,比分足矣牽動我們的心了。這個小插件在我心中種下了學習Python的種子。
開始學習Python階段的抉擇
學習Python,我用的是流暢的Python這本書+官方3.7.2學習文檔,但如果是小白,我推薦你學習網課或者線下報班。
開發語言和正常語言的邏輯都不同,剛開始上手即使是Hello
world的編寫都會讓你頭疼好一陣,實時學習的好處就是,你不懂的地方可以隨時問老師,他們會以最簡單的例子幫你解決這些疑問。
學習Python需要多少時間?
以下我會把各個學習階段學習的時間羅列出來,並附上一段學習經驗。
模塊1:Python基礎知識,控制項結構,函數
時間:1周
學習經驗:學習Python基礎算是Python學習過程中一個很簡單的步驟,但是這個步驟是最重要的,一般在這個階段會將80%的小白勸退,所以一定要堅持下去。
模塊2:面向對象
時間:1周
學習經驗:面向對象的思想也是非常具有挑戰性的一件事,一般我們的思維都是面向過程的,在學習Python基礎語法解決問題也大都是面向過程的思維,想要學好面向對象要接觸大量的項目,只需要了解這些項目的開發人員是如何利用面向對象的思維劃分各個模塊的。
模塊3:GUI編程(Tkinter)
時間:1周
學習經驗:有很多人在學習Python的過程中會忽略這個模塊,但其實學一點GUI對整個Python學習還是有正面的意義的,因為大多數小白最開始對開發的認知停留在各種APP和桌面應用程序,他們都有華麗的界面,但大多數的業務代碼都與GUI無關,這也會打擊一些小白的學習積極性,這時候學習Tkinter庫,去創建幾個簡單的GUI應用程序,會給自己很大的信心。
模塊4:數據分析
時間:1周
學習經驗:了解Numpy和Pandas庫,
Python執行數據分析大多時候都需要用到這兩個庫。如果你想在目前火熱的大數據領域就業,這兩個庫的熟練使用會給你提分不少。除此之外,這也是一些數據從業者比較喜歡的工具之一,比如會計,銀行審計等等,它會教你如何從excel
/ CSV文件處理數據,並用最短的時間將數據可視化。在此過程中,我還了解了 Jupyter notebooks,
它是Python進行數據分析編程最好的IDE工具之一。
模塊5:Django
時間:2周
學習經驗:這是Python學習中最困難的一個模塊了。我以前沒有學習任何關於Web開發的內容,所以花了很多時間惡補了網路通信的知識,比如身份驗證,URL路由,API和模型之類的術語。
在所有知識具備的情況下,用Django自行開發出一個項目,基本可以找第一份工作了。
模塊6:Flask和網路爬蟲
時間:1周
學習經驗:在學習Django之後,Flask可謂小菜一碟,因為Flask只是一個微框架。對於這兩個框架的抉擇,我建議只學習其中一門即可,另外一門看看文檔即可。
網路爬蟲也是一個非常有意思的工具,你可以在網路上利用爬蟲找任何你想要的東西,並讓它自動整合。
模塊7:selenium自動化框架
時間:1周
學習經驗:學習完有關Python的幾乎所有內容後,Selenium就非常簡單了。
Selenium最初用於軟體測試,後來被越來越多的人用作自動化任務。比如我用Selenium做了微信的自動發送功能。
學習這些東西我前前後後花了9-10周的時間,每天大約學習2-3個小時,最終的學習成果我還是很滿意的。
寫在最後
學習完Python之後整個人會很有成就感,兩個月的時間你發覺自己成為了另一個人,雖然這種結果很美好,但是中途要付出太多太多,最重要的還是堅持。還是那句話,如果自製力不好,建議報班。
以上就是小編今天給大家整理發送的關於「想學Python提升自己,應該先從什麼開始?」的全部內容,希望對大家有所幫助。所謂不做不打無准備之仗,總的來說隨著大數據在眾多行業中的應用,大數據技術工作能力的工程師和開發人員是很吃香的。
『叄』 Python性能提升神器!lru_cache的介紹和講解
我們經常談論的緩存一詞,更多的類似於將硬碟中的數據存放到內存中以至於提高讀取速度,比如常說的redis,就經常用來做數據的緩存。 Python的緩存(lru_cache)是一種裝飾在被執行的函數上,將其執行的結果緩存起來,當下次請求的時候,如果請求該函數的傳參未變則直接返回緩存起來的結果而不再執行函數的一種緩存裝飾器。
那它和redis的區別在哪?有什麼優勢?怎麼使用? 下面為你講解
1.現在我們先不使用緩存來寫一個求兩數之和的函數,並調用執行它兩次:
執行結果
可以看到 test 被執行了兩次,現在我們加上緩存再進行執行:
執行結果
可以看到 test 函數只被執行了一次,第二次的調用直接輸出了結果,使用了緩存起來的值。
2.當我們使用遞歸求斐波拉契數列 (斐波那契數列指的是這樣一個數列:0,1,1,2,3,5,8,它從第3項開始,每一項都等於前兩項之和) 的時候,緩存對性能的提升就尤其明顯了:
不使用緩存求第40項的斐波拉契數列
執行時間
使用緩存求第40項的斐波拉契數列:
執行時間
兩個差距是非常明顯的,因為不使用緩存時,相當於要重復執行了很多的函數,而使用了 lru_cache 則把之前執行的函數結果已經緩存了起來,就不需要再次執行了。
查看lru_cache源碼會發現它可以傳遞兩個參數: maxsize 、 typed :
代表被lru_cache裝飾的方法最大可緩存的結果數量 (被裝飾方法傳參不同一樣,則結果不一樣;如果傳參一樣則為同一個結果) , 如果不指定傳參則默認值為128,表示最多緩存128個返回結果,當達到了128個時,有新的結果要保存時,則會刪除最舊的那個結果。如果maxsize傳入為None則表示可以緩存無限個結果;
默認為false,代表不區分數據類型,如果設置為True,則會區分傳參類型進行緩存,官方是這樣描述的:
但在python3.9.8版本下進行測試,typed為false時,按照官方的測試方法測試得到的還是會被當成不同的結果處理,這個時候typed為false還是為true都會區別緩存,這與官方文檔的描述存在差異:
執行結果
但如果是多參數的情況下,則會被當成一個結果:
執行結果
這個時候設置typed為true時,則會區別緩存:
執行結果
當傳參個數大於1時,才符合官方的說法,不清楚是不是官方舉例有誤
當傳遞的參數是dict、list等的可變參數時,lru_cache是不支持的,會報錯:
報錯結果
緩存 緩存位置 是否支持可變參數 是否支持分布式 是否支持過期時間設置 支持的數據結構 需單獨安裝 redis 緩存在redis管理的內存中 是 是 是 支持5種數據結構 是 lru_cache 緩存在應用進程的內存中,應用被關閉則被清空 否 否 否 字典(參數為:key,結果為:value) 否
經過上面的分析,lru_cache 功能相對於redis來說要簡單許多,但使用起來更加方便,適用於小型的單體應用。如果涉及的緩存的數據種類比較多並且想更好的管理緩存、或者需要緩存數據有過期時間(類似登錄驗證的token)等,使用redis是優於lru_cache的。
『肆』 python怎麼提高cpu利用率
內置的是多處理模塊。multiprocessing.Pool類使用map和相關方法在多個CPU之間提供矢量化.但是這里需要權衡.如果必須在進程之間傳遞大量數據,那麼這種開銷可能會抵消多核的優勢。使用合適的numpy版本。如果numpy是使用多線程ATLAS庫構建的,則在遇到大問題時會更快。使用擴展模塊,例如numexpr、parallelpython、corepy或CopenhagenVectorByteCode。請注意,線程模塊在這方面並不是很有用.為了簡化內存管理,全局解釋器鎖(「GIL」)強制一次只能有一個線程執行python位元組碼.但是,像numpy這樣的外部模塊可以在內部使用多個線程.
中央處理器(CPU),是電子計算機的主要設備之一,電腦中的核心配件。其功能主要是解釋計算機指令以及處理計算機軟體中的數據。電腦中所有操作都由CPU負責讀取指令,對指令解碼並執行指令的核心部件。
程序是由指令構成的序列,執行程序就是按指令序列逐條執行指令。一旦把程序裝入主存儲器中,就可以由CPU自動地完成從主存取指令和執行指令的任務。
『伍』 怎樣更好地提高自身的 Python 水平
隨著移動互聯網的普及,伺服器運維所面臨的挑戰也隨之越來越大。當規模增長到一定程度,手動管理方式已經無法應對,自動化運維成為解決問題的銀彈。Python憑借其靈活性,在自動化運維方面已經被廣泛使用,能夠大大提高運維效率,伺服器集群的規模越大,優勢越明顯。現在不論是Linux運維工程師還是Unix運維工程師都需要掌握Python,以提高運維效率。第一個階段:初級,掌握Python的語法和一些常用庫的使用掌握一門語言最好的方法就是用它,所以我覺得邊學語法邊刷Leetcode是掌握Python最快的方式之一。很多隻需要將Python作為腳本或者就是寫一些小程序處理處理文本的話,到這一個階段就足夠了,這個階段已經可以幫我們完成很多很多的事情了。但是如果是一個專業學習Python的,恐怕還需要努力的升級:首先,國內的大多數人都是學習了其他語言(C,C++,Java等)之後來學習Python的,所以Python和這些語言的不同,也就是pythonic的東西需要一些時間去學習了解和掌握;另外,對於自己領域的領域的庫構架的掌握也需要很長的時間去掌握;最後,如果想獨立完成一個Python的項目,項目的布局,發布,開源等都是需要考慮的問題。第二個階段:中級,掌握自己特定領域的庫,掌握pythonic寫法,非常熟悉Python的特性推薦的第一本書是《編寫高質量代碼–改善python程序的91個建議》,這本書大概的提了下Python工程的文件布局,的總結了如何寫出pythonic的代碼,另外,也介紹了一些常用的庫。這里首先推薦在騰訊官方課程渠道上進行直播學習,有號就能無償一直學,每天晚上都是高清直播(企鵝球球:1129中間是834最後加上這個903連在一起就能夠了),除此之外基於python2.7在網上的書籍適合於重頭開始一直讀完,作為一個開發人員,除了基本的語法,這本書裡面提到了一些其他的常用的庫,看了廖老師寫的很多東西,感覺他的思路,以及寫博客寫書的高度,概括性,原理性都十分好,這本書讀完之後,相信就能夠動手寫很多東西了,能夠盡情的玩轉Python解說器了。要想深入的了解Python,有的時候看看Python的源碼也是很重要的,自己通過讀懂源碼,來徹底的了解Python的核心機制,這里推薦《Python源碼剖析——深度探索動態語言核心技術》,這本書並沒有看完,只是在需要深入了解Python某個功能或者數據結構的時候看看相關章節,也覺得受益匪淺。自己領域的書籍和資料也肯定很多,比如web開發的構架都有很多,只有了解熟悉了所有構架,在選擇的時候才能衡量利弊,然後深入掌握某些構架。
『陸』 學python最想要提升的是哪些地方
Python是一門編程語言,是一個較為方便地解決問題的工具。那麼具體提升取決於你未來的崗位。
後台工程師/架構師
如果你的崗位是後台工程師,那麼你要提升的是後台整體技術棧(mysql,redis,消息隊列,多線程),系統設計和針對具體問題提出解決方案的能力。同時你要掌握工程的最佳實踐,例如ci/cd等等。
數據工程師
如果你的崗位是數據工程師,那你需要把python數據處理的常見庫做到精通,你需要了解各個領域的數據處理流程和特性,你需要掌握最近的技術進展
演算法工程師
如果你是演算法工程師,此時Python只是眾多工具中的一個工具而已。如果你是科研方向,你要研究模型和理論本身,此時和語言沒關系了。如果是應用向,即用演算法解決具體的問題,那麼你要提升的是對問題的理解和建模能力,需要提升的是對每一個模型或者演算法的理解深度,在解決實際問題時,要能夠用最合適的演算法解決具體問題。
綜上,Python只是一個具體的工具,本質上要提升的是學習和解決問題的能力。
希望對你有用。
『柒』 「干貨」讓Python性能起飛的15個技巧,你知道幾個呢
前言
Python 一直以來被大家所詬病的一點就是執行速度慢,但不可否認的是 Python 依然是我們學習和工作中的一大利器。本文總結了15個tips有助於提升 Python 執行速度、優化性能。
關於 Python 如何精確地測量程序的執行時間,這個問題看起來簡單其實很復雜,因為程序的執行時間受到很多因素的影響,例如操作系統、Python 版本以及相關硬體(CPU 性能、內存讀寫速度)等。在同一台電腦上運行相同版本的語言時,上述因素就是確定的了,但是程序的睡眠時間依然是變化的,且電腦上正在運行的其他程序也會對實驗有干擾,因此嚴格來說這就是實驗不可重復。
我了解到的關於計時比較有代表性的兩個庫就是 time 和 timeit 。
其中, time 庫中有 time() 、 perf_counter() 以及 process_time() 三個函數可用來計時(以秒為單位),加後綴 _ns 表示以納秒計時(自 Python3.7 始)。在此之前還有 clock() 函數,但是在 Python3.3 之後被移除了。上述三者的區別如下:
與 time 庫相比, timeit 有兩個優點:
timeit.timeit(stmt='pass', setup='pass', timer= , number=1000000, globals=None) 參數說明:
本文所有的計時均採用 timeit 方法,且採用默認的執行次數一百萬次。
為什麼要執行一百萬次呢?因為我們的測試程序很短,如果不執行這么多次的話,根本看不出差距。
Exp1:將字元串數組中的小寫字母轉為大寫字母。
測試數組為 oldlist = ['life', 'is', 'short', 'i', 'choose', 'python']。
方法一
方法二
方法一耗時 0.5267724000000005s ,方法二耗時 0.41462569999999843s ,性能提升 21.29%
Exp2:求兩個 list 的交集。
測試數組:a = [1,2,3,4,5],b = [2,4,6,8,10]。
方法一
方法二
方法一耗時 0.9507264000000006s ,方法二耗時 0.6148200999999993s ,性能提升 35.33%
關於 set() 的語法: | 、 & 、 - 分別表示求並集、交集、差集。
我們可以通過多種方式對序列進行排序,但其實自己編寫排序演算法的方法有些得不償失。因為內置的 sort() 或 sorted() 方法已經足夠優秀了,且利用參數 key 可以實現不同的功能,非常靈活。二者的區別是 sort() 方法僅被定義在 list 中,而 sorted() 是全局方法對所有的可迭代序列都有效。
Exp3:分別使用快排和 sort() 方法對同一列表排序。
測試數組:lists = [2,1,4,3,0]。
方法一
方法二
方法一耗時 2.4796975000000003s ,方法二耗時 0.05551999999999424s ,性能提升 97.76%
順帶一提, sorted() 方法耗時 0.1339823999987857s 。
可以看出, sort() 作為 list 專屬的排序方法還是很強的, sorted() 雖然比前者慢一點,但是勝在它「不挑食」,它對所有的可迭代序列都有效。
擴展 :如何定義 sort() 或 sorted() 方法的 key
1.通過 lambda 定義
2.通過 operator 定義
operator 的 itemgetter() 適用於普通數組排序, attrgetter() 適用於對象數組排序
3.通過 cmp_to_key() 定義,最為靈活
Exp4:統計字元串中每個字元出現的次數。
測試數組:sentence='life is short, i choose python'。
方法一
方法二
方法一耗時 2.8105250000000055s ,方法二耗時 1.6317423000000062s ,性能提升 41.94%
列表推導(list comprehension)短小精悍。在小代碼片段中,可能沒有太大的區別。但是在大型開發中,它可以節省一些時間。
Exp5:對列表中的奇數求平方,偶數不變。
測試數組:oldlist = range(10)。
方法一
方法二
方法一耗時 1.5342976000000021s ,方法二耗時 1.4181957999999923s ,性能提升 7.57%
大多數人都習慣使用 + 來連接字元串。但其實,這種方法非常低效。因為, + 操作在每一步中都會創建一個新字元串並復制舊字元串。更好的方法是用 join() 來連接字元串。關於字元串的其他操作,也盡量使用內置函數,如 isalpha() 、 isdigit() 、 startswith() 、 endswith() 等。
Exp6:將字元串列表中的元素連接起來。
測試數組:oldlist = ['life', 'is', 'short', 'i', 'choose', 'python']。
方法一
方法二
方法一耗時 0.27489080000000854s ,方法二耗時 0.08166570000000206s ,性能提升 70.29%
join 還有一個非常舒服的點,就是它可以指定連接的分隔符,舉個例子
life//is//short//i//choose//python
Exp6:交換x,y的值。
測試數據:x, y = 100, 200。
方法一
方法二
方法一耗時 0.027853900000010867s ,方法二耗時 0.02398730000000171s ,性能提升 13.88%
在不知道確切的循環次數時,常規方法是使用 while True 進行無限循環,在代碼塊中判斷是否滿足循環終止條件。雖然這樣做沒有任何問題,但 while 1 的執行速度比 while True 更快。因為它是一種數值轉換,可以更快地生成輸出。
Exp8:分別用 while 1 和 while True 循環 100 次。
方法一
方法二
方法一耗時 3.679268300000004s ,方法二耗時 3.607847499999991s ,性能提升 1.94%
將文件存儲在高速緩存中有助於快速恢復功能。Python 支持裝飾器緩存,該緩存在內存中維護特定類型的緩存,以實現最佳軟體驅動速度。我們使用 lru_cache 裝飾器來為斐波那契函數提供緩存功能,在使用 fibonacci 遞歸函數時,存在大量的重復計算,例如 fibonacci(1) 、 fibonacci(2) 就運行了很多次。而在使用了 lru_cache 後,所有的重復計算只會執行一次,從而大大提高程序的執行效率。
Exp9:求斐波那契數列。
測試數據:fibonacci(7)。
方法一
方法二
方法一耗時 3.955014900000009s ,方法二耗時 0.05077979999998661s ,性能提升 98.72%
注意事項:
我被執行了(執行了兩次 demo(1, 2) ,卻只輸出一次)
functools.lru_cache(maxsize=128, typed=False) 的兩個可選參數:
點運算符( . )用來訪問對象的屬性或方法,這會引起程序使用 __getattribute__() 和 __getattr__() 進行字典查找,從而帶來不必要的開銷。尤其注意,在循環當中,更要減少點運算符的使用,應該將它移到循環外處理。
這啟發我們應該盡量使用 from ... import ... 這種方式來導包,而不是在需要使用某方法時通過點運算符來獲取。其實不光是點運算符,其他很多不必要的運算我們都盡量移到循環外處理。
Exp10:將字元串數組中的小寫字母轉為大寫字母。
測試數組為 oldlist = ['life', 'is', 'short', 'i', 'choose', 'python']。
方法一
方法二
方法一耗時 0.7235491999999795s ,方法二耗時 0.5475435999999831s ,性能提升 24.33%
當我們知道具體要循環多少次時,使用 for 循環比使用 while 循環更好。
Exp12:使用 for 和 while 分別循環 100 次。
方法一
方法二
方法一耗時 3.894683299999997s ,方法二耗時 1.0198077999999953s ,性能提升 73.82%
Numba 可以將 Python 函數編解碼為機器碼執行,大大提高代碼執行速度,甚至可以接近 C 或 FORTRAN 的速度。它能和 Numpy 配合使用,在 for 循環中或存在大量計算時能顯著地提高執行效率。
Exp12:求從 1 加到 100 的和。
方法一
方法二
方法一耗時 3.7199997000000167s ,方法二耗時 0.23769430000001535s ,性能提升 93.61%
矢量化是 NumPy 中的一種強大功能,可以將操作表達為在整個數組上而不是在各個元素上發生。這種用數組表達式替換顯式循環的做法通常稱為矢量化。
在 Python 中循環數組或任何數據結構時,會涉及很多開銷。NumPy 中的向量化操作將內部循環委託給高度優化的 C 和 Fortran 函數,從而使 Python 代碼更加快速。
Exp13:兩個長度相同的序列逐元素相乘。
測試數組:a = [1,2,3,4,5], b = [2,4,6,8,10]
方法一
方法二
方法一耗時 0.6706845000000214s ,方法二耗時 0.3070132000000001s ,性能提升 54.22%
若要檢查列表中是否包含某成員,通常使用 in 關鍵字更快。
Exp14:檢查列表中是否包含某成員。
測試數組:lists = ['life', 'is', 'short', 'i', 'choose', 'python']
方法一
方法二
方法一耗時 0.16038449999999216s ,方法二耗時 0.04139250000000061s ,性能提升 74.19%
itertools 是用來操作迭代器的一個模塊,其函數主要可以分為三類:無限迭代器、有限迭代器、組合迭代器。
Exp15:返回列表的全排列。
測試數組:["Alice", "Bob", "Carol"]
方法一
方法二
方法一耗時 3.867292899999484s ,方法二耗時 0.3875405000007959s ,性能提升 89.98%
根據上面的測試數據,我繪制了下面這張實驗結果圖,可以更加直觀的看出不同方法帶來的性能差異。
從圖中可以看出,大部分的技巧所帶來的性能增幅還是比較可觀的,但也有少部分技巧的增幅較小(例如編號5、7、8,其中,第 8 條的兩種方法幾乎沒有差異)。
總結下來,我覺得其實就是下面這兩條原則:
內置庫函數由專業的開發人員編寫並經過了多次測試,很多庫函數的底層是用 C 語言開發的。因此,這些函數總體來說是非常高效的(比如 sort() 、 join() 等),自己編寫的方法很難超越它們,還不如省省功夫,不要重復造輪子了,何況你造的輪子可能更差。所以,如果函數庫中已經存在該函數,就直接拿來用。
有很多優秀的第三方庫,它們的底層可能是用 C 和 Fortran 來實現的,像這樣的庫用起來絕對不會吃虧,比如前文提到的 Numpy 和 Numba,它們帶來的提升都是非常驚人的。類似這樣的庫還有很多,比如Cython、PyPy等,這里我只是拋磚引玉。
原文鏈接:https://www.jb51.net/article/238190.htm
『捌』 北大青鳥設計培訓:怎樣才能提高Python運行效率
python逐漸走入人們的視線,成為熱門編程語言,隨之而來,加入python培訓的准程序員大軍也成為社會熱點。
Python具有許多其他編程語言不具備的優勢,譬如能通過極少量代碼完成許多操作,以及多進程,能夠輕松支持多任務處理。
除了多種優勢外,python也有不好的地方,運行較慢,下面電腦培訓http://www.kmbdqn.cn/為大家介紹6個竅門,可以幫你提高python的運行效率。
1.在排序時使用鍵Python含有許多古老的排序規則,這些規則在你創建定製的排序方法時會佔用很多時間,而這些排序方法運行時也會拖延程序實際的運行速度。
最佳的排序方法其實是盡可能多地使用鍵和內置的sort()方法。
2.交叉編譯你的應用開發者有時會忘記計算機其實並不理解用來創建現代應用程序的編程語言。
計算機理解的是機器語言。
為了運行你的應用,你藉助一個應用將你所編的人類可讀的代碼轉換成機器可讀的代碼。
有時,你用一種諸如Python這樣的語言編寫應用,再以C++這樣的語言運行你的應用,這在運行的角度來說,是可行的。
關鍵在於,你想你的應用完成什麼事情,而你的主機系統能提供什麼樣的資源。
3.關鍵代碼使用外部功能包Python簡化了許多編程任務,但是對於一些時間敏感的任務,它的表現經常不盡人意。
使用C/C++或機器語言的外部功能包處理時間敏感任務,可以有效提高應用的運行效率。
這些功能包往往依附於特定的平台,因此你要根據自己所用的平台選擇合適的功能包。
簡而言之,這個竅門要你犧牲應用的可移植性以換取只有通過對底層主機的直接編程才能獲得的運行效率。
4.針對循環的優化每一種編程語言都強調最優化的循環方案。
當使用Python時,你可以藉助豐富的技巧讓循環程序跑得更快。
然而,開發者們經常遺忘的一個技巧是:盡量避免在循環中訪問變數的屬性。
5.嘗試多種編碼方法每次創建應用時都使用同一種編碼方法幾乎無一例外會導致應用的運行效率不盡人意。
可以在程序分析時嘗試一些試驗性的辦法。
譬如說,在處理字典中的數據項時,你既可以使用安全的方法,先確保數據項已經存在再進行更新,也可以直接對數據項進行更新,把不存在的數據項作為特例分開處理。
6.使用較新的Python版本你要保證自己的代碼在新版本里還能運行。
你需要使用新的函數庫才能體驗新的Python版本,然後你需要在做出關鍵性的改動時檢查自己的應用。
只有當你完成必要的修正之後,你才能體會新版本的不同。
『玖』 如何提升Python編程能力
一、Python之禪(The Zen of Python)
The Zen of Python是Python語言的指導原則,遵循這些基本原則,你就可以像個Pythonista一樣編程。具體內容你可以在Python命令行輸入import this看到:
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
# 優美勝於醜陋(Python以編寫優美的代碼為目標)
Explicit is better than implicit.
# 明了勝於晦澀(優美的代碼應當是明了的,命名規范,風格相似)
Simple is better than complex.
# 簡潔勝於復雜(優美的代碼應當是簡潔的,不要有復雜的內部實現)
Complex is better than complicated.
# 復雜勝於凌亂(如果復雜不可避免,那代碼間也不能有難懂的關系,要保持介面簡潔)
Flat is better than nested.
# 扁平勝於嵌套(優美的代碼應當是扁平的,不能有太多的嵌套)
Sparse is better than dense.
# 間隔勝於緊湊(優美的代碼有適當的間隔,不要奢望一行代碼解決問題)
Readability counts.
# 可讀性很重要(優美的代碼是可讀的)
Special cases aren't special enough to break the rules.
Although practicality beats purity.
# 即便假借特例的實用性之名,也不可違背這些規則(這些規則至高無上)
Errors should never pass silently.
Unless explicitly silenced.
# 不要包容所有錯誤,除非你確定需要這樣做(精準地捕獲異常,不寫except:pass風格的代碼)
In the face of ambiguity, refuse the temptation to guess.
# 當存在多種可能,不要嘗試去猜測
There should be one-- and preferably only one --obvious way to do it.
# 而是盡量找一種,最好是唯一一種明顯的解決方案(如果不確定,就用窮舉法)
Although that way may not be obvious at first unless you're Dutch.
# 雖然這並不容易,因為你不是 Python 之父(這里的Dutch是指Guido)
Now is better than never.
Although never is often better than *right* now.
# 做也許好過不做,但不假思索就動手還不如不做(動手之前要細思量)
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
# 如果你無法向人描述你的方案,那肯定不是一個好方案;反之亦然(方案測評標准)
Namespaces are one honking great idea -- let's do more of those!
# 命名空間是一種絕妙的理念,我們應當多加利用(倡導與號召)
這首特別的「詩」開始作為一個笑話,但它確實包含了很多關於Python背後的哲學真理。Python之禪已經正式成文PEP 20,具體內容見:PEP 20
二、PEP8: Python編碼規范(PEP8: Style Guide for Python Code)
Abelson & Sussman在《計算機程序的構造和解釋》一書中說道:程序是寫來給人讀的,只是順帶讓機器執行。所以,我們在編碼時應該盡量讓它更易讀懂。PEP8是Python的編碼規范,官方文檔見:PEP 8,PEP是Python Enhancement Proposal的縮寫。PEP8包括很多編碼的規范,下面主要介紹一下縮進和命名等內容。
空格和縮進(WhiteSpace and Indentation)
空格和縮進在Python語言中非常重要,它替代了其他語言中{}的作用,用來區分代碼塊和作用域。在這方面PEP8有以下的建議:
1、每次縮進使用4個空格
2、不要使用Tab,更不要Tab和空格混用
3、兩個方法之間使用一個空行,兩個Class之間使用兩個空行
4、添加一個空格在字典、列表、序列、參數列表中的「,「後,以及在字典中的」:「之後,而不是之前
5、在賦值和比較兩邊放置一個空格(參數列表中除外)
6、緊隨括弧後面或者參數列表前一個字元不要存在空格
Python命名
命名規范是編程語言的基礎,而且大部分的規范對於高級語言來說都是一樣的,Python的基本規范如下:
1、方法 & 屬性:joined_lower
2、常量:joined_lower or ALL_CAPS
3、類:StudlyCaps
4、類屬性:interface, _internal, __private
5、camelCase only to conform to pre-existing conventions
以上內容只是對PEP8做了非常簡單的介紹,由於今天的主題不在於此,所以就不在這里多講。想要更加深入的了解Python編碼規范,可以閱讀PEP8官方文檔和Google Python編碼規范等內容。
三、交換變數值(Swap Values)
在其他語言中,交換兩個變數值的時候,可以這樣寫:
temp = a
a = b
b = temp
在Python中,我們可以簡單的這樣寫:
b, a = a, b
可能你已經在其他地方見過這種寫法,但是你知道Python是如何實現這種語法的嗎?首先,逗號(,)是Python中tuple數據結構的語法;上面的語法會執行一下的操作:
1、Python會先將右邊的a, b生成一個tuple(元組),存放在內存中;
2、之後會執行賦值操作,這時候會將tuple拆開;
3、然後將tuple的第一個元素賦值給左邊的第一個變數,第二個元素賦值給左邊第二個變數。
再舉個tuple拆分的例子:
In [1]: people = ['David', 'Pythonista', '15145551234']
In [2]: name, title, phone = people
In [3]: name
Out[3]: 'David'
In [4]: title
Out[4]: 'Pythonista'
In [5]: phone
Out[5]: '15145551234'
這種語法在For循環中非常實用:
In [6]: people = [['David', 'Pythonista', '15145551234'], ['Wu', 'Student', '15101365547']]
In [7]: for name, title, phone in people:
...: print name, phone
...:
David 15145551234
Wu 15101365547
PS:在使用這種語法時,需要確保左邊的變數個數和右邊tuple的個數一致,否則,Python會拋出ValueError異常。
更多tuple的例子:
>>> 1,
(1,)
>>> (1,)
(1,)
>>> (1)
1
>>> value = 1,
>>> value
(1,)
我們知道:逗號(,)在Python中是創建tuple的構造器,所以我們可以按照上面的方式很方便的創建一個tuple;需要注意的是:如果聲明只有一個元素的tuple,末尾必須要帶上逗號,兩個以上的元素則不需要。聲明tuple的語法很簡單,但同時它也比較坑:如果你發現Python中的變數不可思議的變成了tuple,那很可能是因為你多寫了一個逗號。。
四、Python控制台的"_"(Interactive "_")
這是Python中比較有用的一個功能,不過有很多人不知道(我也是接觸Python很久之後才知道的)。。在Python的互動式控制台中,當你計算一個表達式或者調用一個方法的時候,運算的結果都會放在一個臨時的變數 _ 裡面。_(下劃線)用來存儲上一次的列印結果,比如:
>>> import math
>>> math.pi / 3
1.0471975511965976
>>> angle = _
>>> math.cos(angle)
0.50000000000000011
>>> _
0.50000000000000011
PS:當返回結果為None的時候,控制台不會列印,_ 裡面存儲的值也就不會改變。
五、合並字元串(Building Strings from Sub strings)
假如現在有一個list,裡面是一些字元串,你現在需要將它們合並成一個字元串,最簡單的方法,你可以按照下面的方式去處理:
colors = ['red', 'blue', 'green', 'yellow']
result = ''
for s in colors:
result += s
但是,很快你會發現:這種方法非常低效,尤其當list非常大的時候。Python中的字元串對象是不可改變的,因此對任何字元串的操作如拼接,修改等都將產生一個新的字元串對象,而不是基於原字元串。所以,上面的方法會消耗很大的內存:它需要計算,存儲,同時扔掉中間的計算結果。正確的方法是使用Python中的join方法:
result = ','.join(colors)
當合並元素比較少的時候,使用join方法看不出太大的效果;但是當元素多的時候,你會發現join的效率還是非常明顯的。不過,在使用的時候請注意:join只能用於元素是字元串的list,它不會進行任何的強制類型轉換。連接一個存在一個或多個非字元串元素的list時將拋出異常。
『拾』 如何提高python的運行效率
竅門一:關鍵代碼使用外部功能包
Python簡化了許多編程任務,但是對於一些時間敏感的任務,它的表現經常不盡人意。使用C/C++或機器語言的外部功能包處理時間敏感任務,可以有效提高應用的運行效率。這些功能包往往依附於特定的平台,因此你要根據自己所用的平台選擇合適的功能包。簡而言之,這個竅門要你犧牲應用的可移植性以換取只有通過對底層主機的直接編程才能獲得的運行效率。以下是一些你可以選擇用來提升效率的功能包:
Cython
Pylnlne
PyPy
Pyrex
這些功能包的用處各有不同。比如說,使用C語言的數據類型,可以使涉及內存操作的任務更高效或者更直觀。Pyrex就能幫助Python延展出這樣的功能。Pylnline能使你在Python應用中直接使用C代碼。內聯代碼是獨立編譯的,但是它把所有編譯文件都保存在某處,並能充分利用C語言提供的高效率。
竅門二:在排序時使用鍵
Python含有許多古老的排序規則,這些規則在你創建定製的排序方法時會佔用很多時間,而這些排序方法運行時也會拖延程序實際的運行速度。最佳的排序方法其實是盡可能多地使用鍵和內置的sort()方法。譬如,拿下面的代碼來說:
import operator
somelist = [(1, 5,]
在每段例子里,list都是根據你選擇的用作關鍵參數的索引進行排序的。這個方法不僅對數值類型有效,還同樣適用於字元串類型。
竅門三:針對循環的優化
每一種編程語言都強調最優化的循環方案。當使用Python時,你可以藉助豐富的技巧讓循環程序跑得更快。然而,開發者們經常遺忘的一個技巧是:盡量避免在循環中訪問變數的屬性。譬如,拿下面的代碼來說:
lowerlist = ['this', 'is', 'lowercase']
upper = str.upper
upperlist = []
append = upperlist.append
for word in lowerlist:
append(upper(word))
print(upperlist)
#Output = ['THIS', 'IS', 'LOWERCASE']
每次你調用str.upper, Python都會計算這個式子的值。然而,如果你把這個求值賦值給一個變數,那麼求值的結果就能提前知道,Python程序就能運行得更快。因此,關鍵就是盡可能減小Python在循環中的工作量。因為Python解釋執行的特性,在上面的例子中會大大減慢它的速度。
(注意:優化循環的方法還有很多,這只是其中之一。比如,很多程序員會認為,列表推導式是提高循環速度的最佳方法。關鍵在於,優化循環方案是提高應用程序運行速度的上佳選擇。)
竅門四:使用較新的Python版本
如果你在網上搜索Python,你會發現數不盡的信息都是關於如何升級Python版本。通常,每個版本的Python都會包含優化內容,使其運行速度優於之前的版本。但是,限制因素在於,你最喜歡的函數庫有沒有同步更新支持新的Python版本。與其爭論函數庫是否應該更新,關鍵在於新的Python版本是否足夠高效來支持這一更新。
你要保證自己的代碼在新版本里還能運行。你需要使用新的函數庫才能體驗新的Python版本,然後你需要在做出關鍵性的改動時檢查自己的應用。只有當你完成必要的修正之後,你才能體會新版本的不同。
然而,如果你只是確保自己的應用在新版本中可以運行,你很可能會錯過新版本提供的新特性。一旦你決定更新,請分析你的應用在新版本下的表現,並檢查可能出問題的部分,然後優先針對這些部分應用新版本的特性。只有這樣,用戶才能在更新之初就覺察到應用性能的改觀。
竅門五:嘗試多種編碼方法
每次創建應用時都使用同一種編碼方法幾乎無一例外會導致應用的運行效率不盡人意。可以在程序分析時嘗試一些試驗性的辦法。譬如說,在處理字典中的數據項時,你既可以使用安全的方法,先確保數據項已經存在再進行更新,也可以直接對數據項進行更新,把不存在的數據項作為特例分開處理。請看下面第一段代碼:
n = 16
myDict = {}
for i in range(0, n):
char = 'abcd'[i%4]
if char not in myDict:
myDict[char] = 0
myDict[char] += 1
print(myDict)
當一開始myDict為空時,這段代碼會跑得比較快。然而,通常情況下,myDict填滿了數據,至少填有大部分數據,這時換另一種方法會更有效率。
n = 16
myDict = {}
for i in range(0, n):
char = 'abcd'[i%4]
try:
myDict[char] += 1
except KeyError:
myDict[char] = 1
print(myDict)
在兩種方法中輸出結果都是一樣的。區別在於輸出是如何獲得的。跳出常規的思維模式,創建新的編程技巧能使你的應用更有效率。
竅門六:交叉編譯你的應用
開發者有時會忘記計算機其實並不理解用來創建現代應用程序的編程語言。計算機理解的是機器語言。為了運行你的應用,你藉助一個應用將你所編的人類可讀的代碼轉換成機器可讀的代碼。有時,你用一種諸如Python這樣的語言編寫應用,再以C++這樣的語言運行你的應用,這在運行的角度來說,是可行的。關鍵在於,你想你的應用完成什麼事情,而你的主機系統能提供什麼樣的資源。
Nuitka是一款有趣的交叉編譯器,能將你的Python代碼轉化成C++代碼。這樣,你就可以在native模式下執行自己的應用,而無需依賴於解釋器程序。你會發現自己的應用運行效率有了較大的提高,但是這會因平台和任務的差異而有所不同。
(注意:Nuitka現在還處在測試階段,所以在實際應用中請多加註意。實際上,當下最好還是把它用於實驗。此外,關於交叉編譯是否為提高運行效率的最佳方法還存在討論的空間。開發者已經使用交叉編譯多年,用來提高應用的速度。記住,每一種解決辦法都有利有弊,在把它用於生產環境之前請仔細權衡。)
在使用交叉編譯器時,記得確保它支持你所用的Python版本。Nuitka支持Python2.6, 2.7, 3.2和3.3。為了讓解決方案生效,你需要一個Python解釋器和一個C++編譯器。Nuitka支持許多C++編譯器,其中包括Microsoft Visual Studio,MinGW 和 Clang/LLVM。
交叉編譯可能造成一些嚴重問題。比如,在使用Nuitka時,你會發現即便是一個小程序也會消耗巨大的驅動空間。因為Nuitka藉助一系列的動態鏈接庫(DDLs)來執行Python的功能。因此,如果你用的是一個資源很有限的系統,這種方法或許不太可行。