Python中的優(yōu)化,大神的程序比我們寫的快五倍,原來是這樣做的!
Python是一種強大的編程語言。而且我們可以做到這一點,使代碼更輕更快。它不僅支持多處理功能,而且輕松實現。下面我們列出了一些***的Python代碼優(yōu)化技巧和技巧。
Python批評者有時會聲稱它很慢。但是這不是因為Python,而是由于用于編寫代碼的做法。在這篇文章中,您將找到加速您的Python應用程序的提示。
由于Python是功能豐富的語言,所以總是有改進的余地。如果您希望使您的Python代碼運行得更快更有效率,那么請繼續(xù)閱讀。
這些技巧和Python的優(yōu)點在于所有的優(yōu)化技術實際上都在Python領域。你只需要知道它們,并在編碼時以有紀律的方式實施。最近我們寫了一篇關于三十個基本Python編程技巧和技巧的文章。你也可以檢查出來,找到你不知道的東西。
我們首先從Python的一些核心內部開始,你可以利用它來獲得優(yōu)勢。
基本的Python代碼優(yōu)化技巧和技巧的極客。
國際弦樂效率。
實現字符串是一種僅存儲每個不同字符串的單個副本的方法。我們可以通過操作我們的代碼來觸發(fā)字符串的實現,使Python解釋器重用字符串。
通常,當我們創(chuàng)建一個字符串對象時,由Python解釋器決定是否緩存字符串。在處理標識符的某些條件下,它是解釋器的固有本質。
聲明一個字符串,其名稱以字母或下劃線開頭,僅包含字母/下劃線/數字組合,將使Python嵌入字符串并為其創(chuàng)建散列。
由于Python有很多使用字典的內部代碼,這導致它執(zhí)行no。的搜索標識符。因此,在標識符串之間實行加速整個過程。簡而言之,Python將所有標識符保留在表中,并為每個對象生成唯一的密鑰(散列),以便將來查找。此優(yōu)化在編譯期間進行。它還結合了類似于標識符的字符串文字的實習。
所以在Python中這是一個非常有用的功能,你可以利用它來獲得好處。這樣的功能可以幫助您加快對大型文本挖掘或分析應用程序的處理。因為他們需要頻繁的搜索和觸發(fā)信息的記賬。
您從文件中讀取或通過網絡通信接收的字符串不是Python中自動實習的一部分。相反,您可以將此任務卸載到用于處理此類字符串的intern()函數。
窺視孔優(yōu)化技術。
窺視孔優(yōu)化是從程序或程序的一部分優(yōu)化一小段指令的方法。這個段被稱為<Peephole>或<Window>。它可以幫助您找到可以用最小化版本替換的說明。
我們來看看Python如何處理窺視孔優(yōu)化。它有一個內置的方法,從下面的例子中查看。
實施例-1。
該示例具有初始化其兩個成員的功能。其中一個是字符串,而另一個是整數。接下來的另一個代碼屬性被添加到函數中,并且默認為<無>。有趣的是四個文字將作為常數留在記憶中。請參考下面給出的圖像。
Python代碼優(yōu)化提示和技巧 - 示例(1)
在附加的快照中,您可以看到我們使用了常量<.__代碼__。co_consts>。它是Python中每個功能對象的三個元組之一。是的,一個函數也是Python中的一個對象。它包括以下三個元組。
1. <__ code __。co_varnames>:保存包含參數的局部變量。
2. <__ code __。co_names>:存儲全局文字。
3. <__ code __。co_consts>:引用所有常量。
現在,窺探孔優(yōu)化可以做的更多,就是把可變結構變成不可變的。參考下面的例子。
例2。
在這個例子中,我們使用“in”運算符搜索集合中的一個特定元素。這里,Python會檢測到該集合將用于驗證元素的成員資格。因此,無論集合的大小如何,它都會將指令視為不變成本操作。并且將比在元組或列表的情況下更快地處理它們。這種方法被稱為Python中的成員身份測試。請仔細檢查附件的截圖。
Python代碼優(yōu)化提示和技巧 - 示例(2)
實施例-3。
盡管如此,如果您以與上一個示例中的集合相似的方式使用列表對象,則Python將其轉換為元組常量。現在,在這個例子中,我們已經將這個集合和列表的用法結合在一起了。并顯示兩個對象都被轉換成常量。請參考附件截圖。
Python代碼優(yōu)化技巧與竅門 - 示例(3)
同樣的事實,我們可以驗證看翻譯代碼的字節(jié)碼。為此,我們必須導入Python的“dis”模塊。并將函數對象作為參數傳遞給“dis”構造函數,將按字節(jié)碼打印整個內存布局。
Python代碼優(yōu)化提示和技巧 - 示例(4)
從附件圖像中的“dis”輸出,很容易驗證集合和列表是否已經變?yōu)槌A俊?/p>
這里的主旨是Python只對文字進行了這種轉換。如果上述示例中使用的任何set / list不是文字,那么優(yōu)化就不會發(fā)生。
配置你的代碼
在進一步深入優(yōu)化您的代碼之前,如果您不知道瓶頸在哪里,那將是天真的。所以首先,使用下面提到的兩種方法中的任何一種來配置你的代碼。
3.1。使用<Timeit>進行秒表分析。
這是使用Python的<timeit>模塊進行分析的傳統(tǒng)方式。它記錄代碼段執(zhí)行的時間。它測量以毫秒為單位的時間。
上面的例子表明,join方法比其他方法更有效率。
3.2。使用<CProfile>進行高級分析。
從Python 2.5開始,cProfile是Python包的一部分。它提供了一組不錯的分析功能來隔離代碼中的瓶頸。你可以用許多方式與你的代碼綁定。喜歡,在其運行方法中包裝一個函數來測量性能。或者,在Python的“-m”選項的幫助下,通過命令行運行整個腳本,同時激活cProfile作為參數。
在這里,我們將展示一些基本的例子,以便您了解如何使用它。
3.2.1。示例(1) - 在Python中使用CProfile。
查看結果,您可以調查有待改進的領域。更有用的是,我們可以在運行腳本時附加cProfile。
3.2.2。示例(2) - 在Python中使用CProfile。
3.2.3。如何解釋CProfile結果?
從分析結果中找出禍患更為重要。只有知道構成cProfile報告的關鍵要素,才能作出決定。
1. <ncalls>:這是調用的次數。
2. <tottime>:這是在給定函數中花費的總時間。
3. <percall>:表示<tottime>除以<ncalls>的商。
4. <cumtime>:執(zhí)行函數及其子功能的累積時間。
5. <percall>:表示<cumtime>除以原始調用的商。
6. <filename_lineno(function)>:程序中的操作點。這可能是一條線。或文件中某個位置的函數。
現在,您已經檢查了所有分析報告的元素。所以你可以去尋找程序的可能部分,在代碼中創(chuàng)建瓶頸。
首先,開始檢查最重要的<tottime>和<cumtime>。有時候,<ncalls>也可能是相關的。對于其余的項目,您需要自己練習。
4.使用發(fā)電機和鑰匙進行排序。
發(fā)電機是內存優(yōu)化的好工具。它們有助于創(chuàng)建一次可以返回一個項目(迭代器)的函數,而不是一次返回所有的項目。一個很好的例子是當你創(chuàng)建一個巨大的數字列表,并將它們相加在一起。
此外,在列表中排序項目時,應盡可能使用鍵和默認的<sort()>方法。在下面的示例中,檢查我們是否按照作為鍵參數的一部分選擇的索引對列表進行排序。同樣的方法,你可以使用字符串。
5.優(yōu)化循環(huán)。
大多數編程語言強調需要優(yōu)化循環(huán)。在Python中,我們確實有一種使循環(huán)執(zhí)行得更快的方法。考慮程序員經常錯過的方法是阻止在循環(huán)中使用點。
在Python中,您會看到一些支持循環(huán)的構建塊。在這些少數中,使用“for”循環(huán)是普遍的。雖然你可能喜歡使用循環(huán),但是他們來代價。Python引擎在解釋for循環(huán)構造方面付出了巨大的努力。因此,***用內置的結構(如地圖)替換它們。
接下來,代碼優(yōu)化的水平也取決于你對Python內置功能的了解。在下面的例子中,我們將嘗試解釋不同的構造如何幫助優(yōu)化循環(huán)。
5.1。用于優(yōu)化Python中For循環(huán)的插圖。
實施例-1。
讓我們考慮一個更新Zipcodes列表的功能,剝離尾隨空格,并使用for循環(huán)。
例2。
現在,看看如何使用地圖對象將上述內容翻譯成單行。現在也更具成本效益。
實施例-3。
我們甚至可以使用列表推導使語法更線性化。
實施例-4。
***,最快的方法是將for循環(huán)轉換為生成器表達式。
5.2。讓我們解碼我們優(yōu)化了什么?
如上所述,使用生成器表達式是在上述用例(通常)中優(yōu)化for循環(huán)的最快方法。我們分析了四個示例的代碼,以便您也可以看到每種方法獲得的性能提升。
6.使用設置操作。
Python使用哈希表來管理集合。每當我們向一個集合添加一個元素時,Python解釋器將使用目標元素的散列來確定其在為集合分配的內存中的位置。
由于Python自動調整散列表的大小,所以無論設置的大小如何,速度都可以是常數(O(1))。這就是集合操作執(zhí)行得更快。
在Python中,設置操作包括聯合,交集和差異。所以你可以嘗試在你的代碼中使用它們。這些通常比迭代列表快。
7.避免使用全局變量。
它不僅限于Python,幾乎所有的語言都不允許使用全局變量的過度或計劃外使用。背后的原因是他們可能會隱藏/不明顯的副作用導致意大利面條代碼。此外,Python在訪問外部變量方面真的很慢。
然而,它允許有限地使用全局變量。您可以使用global關鍵字聲明一個外部變量。另外,在使用它們的內部循環(huán)之前做一個本地的副本。
8.使用外部庫/包。
一些python庫具有與原始庫相同特征的“C”等價物。被寫入“C”使它們執(zhí)行速度更快。例如,嘗試使用cPickle而不是使用pickle。
接下來,您可以使用<Cython>,這是Python的優(yōu)化靜態(tài)編譯器。它是Python的超集,并帶來C函數和類型的支持。它指示編譯器生成快速高效的代碼。
您也可以考慮使用PyPy軟件包。它包括一個JIT(即時)編譯器,使Python代碼運行速度快。你甚至可以調整它來提供額外的處理能力。
9.使用內置操作符。
Python是一種解釋型語言,基于高級抽象。所以你應該盡可能使用內置的。這將使您的代碼更有效率,因為內置的預編譯和快速。而包括解釋步驟在內的漫長迭代很慢。
同樣,喜歡使用內置功能,如地圖,顯著改善速度。
10.在循環(huán)中限制方法查找。
在循環(huán)中工作時,應該緩存方法調用,而不是在對象上調用它。否則,方法查找是昂貴的。
請考慮以下示例。
11.使用字符串進行優(yōu)化。
字符串連接緩慢,不要在循環(huán)中執(zhí)行。而是使用Python的join方法。或者,使用格式化功能來形成一個統(tǒng)一的字符串。
Python中的RegEx操作很快就被推回到C代碼。然而,在某些情況下,基本的字符串方法(如<isalpha()/ isdigit()/ startswith()/ endswith()>更好地工作。
此外,您可以使用<timeit>模塊測試不同的方法。它將幫助您確定哪種方法是真正最快的。
12.用If語句進行優(yōu)化。
像大多數編程語言一樣,懶惰 - 如果評估,Python也是如此。這意味著,如果加入“AND”條件,那么并非所有條件都將被測試,以防其中一個變?yōu)榧佟?/p>
1.你可以調整你的代碼使用Python的這種行為。例如,如果要在列表中搜索固定模式,則可以通過添加以下條件來減小范圍。
如果目標字符串的大小小于模式的長度,則添加一個“AND”條件,該條件變?yōu)閒alse。
此外,您可以首先測試一個快速條件(如果有的話),如“string應該以@開頭”或“string應該以點結尾”。
2.您可以測試比< > 更快的條件< not >。like ifdoneis None ifdone!=None
摘要 - Python代碼優(yōu)化提示和技巧。
我們希望本文中給出的方法可以幫助您構建更快的Python應用程序。但是,在應用這些提示時,請注意,只有在您的代碼中建立了灰色區(qū)域時,才能進行優(yōu)化。
您可以直接在編碼實踐中采用一些提示。就像使用剖析方法一樣,它們是給您正確的方向,并引導優(yōu)化的道路。
除了上述提示之外,您必須檢查代碼以進行二次行為。您應該了解不同Python構造的時間復雜性,如列表,集合和集合。***,盡可能收集數據,這將有助于您確定您正在做的是否對。