python高性能編程方法

毫無疑問Python程序沒有編譯型語言高效快速. 甚至Python擁護者們會告訴你Python不適合這些領域. 然而,YouTube已用Python服務于每小時4千萬視頻的請求. 你所要做的就是編寫高效的代碼和需要時使用外部實現(C/C++)代碼. 這里有一些建議,可以幫助你成為一個更好的Python開發者:

  1. 使用內建函數: 你可以用Python寫出高效的代碼,但很難擊敗內建函數. 經查證. 他們非常快速.2.使用join()連接字符串. 你可以使用 "+" 來連接字符串. 但由于string在Python中是不可變的,每一個"+"操作都會創建一個新的字符串并復制舊內容. 常見用法是使用Python的數組模塊單個的修改字符;當完成的時候,使用 join() 函數創建最終字符串.
for chunk in input():
       my_string.join(chunk)
  1. 使用Python多重賦值,交換變量
    這在Python中即優雅又快速:
      x, y = y, x
 這樣很慢:
    temp = x
    x = y
    y = temp   
  1. 盡量使用局部變量
    Python 檢索局部變量比檢索全局變量快. 這意味著,避免 "global" 關鍵字.
  2. 盡量使用 "in"
    使用 "in" 關鍵字. 簡潔而快速.
      for key in sequence:
          print “found”
  1. 使用延遲加載加速
    將 "import" 聲明移入函數中,僅在需要的時候導入. 換句話說,如果某些模塊不需馬上使用,稍后導入他們. 例如,你不必在一開使就導入大量模塊而加速程序啟動. 該技術不能提高整體性能. 但它可以幫助你更均衡的分配模塊的加載時間.
  2. 為無限循環使用 "while 1"
    有時候在程序中你需一個無限循環.(例如一個監聽套接字的實例) 盡管 "while true" 能完成同樣的事, 但 "while 1" 是單步運算. 這招能提高你的Python性能.
       while 1:
         #do stuff, faster with while 1
       while True:
        # do stuff, slower with wile True
  1. 使用list comprehension
    從Python 2.0 開始,你可以使用 list comprehension 取代大量的 "for" 和 "while" 塊. 使用List comprehension通常更快,Python解析器能在循環中發現它是一個可預測的模式而被優化.額外好處是,list comprehension更具可讀性(函數式編程),并在大多數情況下,它可以節省一個額外的計數變量。例如,讓我們計算1到10之間的偶數個數:
     # the good way to iterate a range
     evens = [ i for i in range(10) if i%2 == 0]
     [0, 2, 4, 6, 8]
      # the following is not so Pythonic
      i = 0
     evens = []
     while i < 10:
           if i %2 == 0: evens.append(i)
               i += 1
     [0, 2, 4, 6, 8]
  1. 使用xrange()處理長序列:
    這樣可為你節省大量的系統內存,因為xrange()在序列中每次調用只產生一個整數元素。而相反 range(),它將直接給你一個完整的元素列表,用于循環時會有不必要的開銷。
  2. 使用 Python generator:
    這也可以節省內存和提高性能。例如一個視頻流,你可以一個一個字節塊的發送,而不是整個流。例如, ```python
    chunk = ( 1000 * i for i in xrange(1000))
    chunk
    <generator object at 0x7f65d90dcaa0>
    chunk.next()
    0
    chunk.next()
    1000
    chunk.next()
    2000
  3. 了解itertools模塊:
    該模塊對迭代和組合是非常有效的。讓我們生成一個列表[1,2,3]的所有排列組合,僅需三行Python代碼:
     import itertools
     iter = itertools.permutations([1,2,3])
     list(iter)
     [(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]
  1. 學習bisect模塊保持列表排序:
    這是一個免費的二分查找實現和快速插入有序序列的工具。也就是說,你可以使用:
     import bisect
     bisect.insort(list, element)
 你已將一個元素插入列表中, 而你不需要再次調用 sort() 來保持容器的排序, 因為這在長序列中這會非常昂貴.
  1. 理解Python列表,實際上是一個數組:
    Python中的列表實現并不是以人們通常談論的計算機科學中的普通單鏈表實現的。Python中的列表是一個數組。也就是說,你可以以常量時間O(1) 檢索列表的某個元素,而不需要從頭開始搜索。這有什么意義呢? Python開發人員使用列表對象insert()時, 需三思. 例如:>>> list.insert(0,item)
    在列表的前面插入一個元素效率不高, 因為列表中的所有后續下標不得不改變. 然而,您可以使用list.append()在列表的尾端有效添加元素. 挑先deque,如果你想快速的在兩插入或時。它是快速的,因為在Python中的deque用雙鏈表實現。不再多說。
  2. 使用dict 和 set 測試成員: 檢查一個元素是在dicitonary或set是否存在 這在Python中非常快的。這是因為dict和set使用哈希表來實現。查找效率可以達到O(1)。因此,如果您需要經常檢查成員,使用 set 或 dict做為你的容器.
     mylist = ['a', 'b', 'c'] #Slower, check membership with list:
      ‘c’ in mylist
     True
     myset = set(['a', 'b', 'c']) # Faster, check membership with set:
     ‘c’ in myset:
     True
  1. 使用Schwartzian Transform 的 sort():
    原生的list.sort()函數是非常快的。 Python會按自然順序排序列表。有時,你需要非自然順序的排序。例如,你要根據服務器位置排序的IP地址。 Python支持自定義的比較,你可以使用list.sort(CMP()),這會比list.sort()慢,因為增加了函數調用的開銷。如果性能有問 題,你可以申請Guttman-Rosler Transform,基于Schwartzian Transform. 它只對實際的要用的算法有興趣,它的簡要工作原理是,你可以變換列表,并調用Python內置list.sort() - > 更快,而無需使用list.sort(CMP() )->慢。
  2. Python裝飾器緩存結果:
    “@”符號是Python的裝飾語法。它不只用于追查,鎖或日志。你可以裝飾一個Python函數,記住調用結果供后續使用。這種技術被稱為memoization的。下面是一個例子:
     from functools import wraps
     def memo(f):
           cache = { }
           @wraps(f)
           def  wrap(*arg):
                  if arg not in cache: cache['arg'] = f(*arg)
                        return cache['arg']
           return wrap
 我們也可以對 Fibonacci 函數使用裝飾器:
     @memo
     def fib(i):
           if i < 2: return 1
                return fib(i-1) + fib(i-2)
這里的關鍵思想是:增強函數(裝飾)函數,記住每個已經計算的Fibonacci值;如果它們在緩存中,就不需要再計算了.
  1. 理解Python的GIL(全局解釋器鎖):
    GIL是必要的,因為CPython的內存管理是非線程安全的。你不能簡單地創建多個線程,并希望Python能在多核心的機器上運行得更快。這是因為 GIL將會防止多個原生線程同時執行Python字節碼。換句話說,GIL將序列化您的所有線程。然而,您可以使用線程管理多個派生進程加速程序,這些程 序獨立的運行于你的Python代碼外。
  2. 像熟悉文檔一樣的熟悉Python源代碼:
    Python有些模塊為了性能使用C實現。當性能至關重要而官方文檔不足時,可以自由探索源代碼。你可以找到底層的數據結構和算法。 Python的源碼庫就是一個很棒的地方:http://svn.python.org/view/python/trunk/Modules
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,316評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,481評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,241評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,939評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,697評論 6 409
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,182評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,247評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,406評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,933評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,772評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,973評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,516評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,638評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,866評論 1 285
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,644評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,953評論 2 373

推薦閱讀更多精彩內容