亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Python > 正文

python編碼最佳實踐之總結

2020-01-04 17:45:52
字體:
來源:轉載
供稿:網友
python編碼最佳實踐之總結,幫助大家整理了python編碼最佳實踐的相關知識點,重點從性能角度出發對python的一些慣用法做一個簡單總結,感興趣的小伙伴們可以參考一下
 

相信用python的同學不少,本人也一直對python情有獨鐘,毫無疑問python作為一門解釋性動態語言沒有那些編譯型語言高效,但是python簡潔、易讀以及可擴展性等特性使得它大受青睞。

 工作中很多同事都在用python,但往往很少有人關注它的性能和慣用法,一般都是現學現用,畢竟python不是我們的主要語言,我們一般只是使用它來做一些系統管理的工作。但是我們為什么不做的更好呢?python zen中有這樣一句: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鼓勵使用一種最優的方法去完成一件事,這也是和ruby等的一個差異。所以一種好的python編寫習慣個人認為很重要,本文就重點從性能角度出發對python的一些慣用法做一個簡單總結,希望對大家有用~

    提到性能,最容易想到的是降低復雜度,一般可以通過測量代碼回路復雜度(cyclomatic complexitly)和Landau符號(大O)來分析, 比如dict查找是O(1),而列表的查找卻是O(n),顯然數據的存儲方式選擇會直接影響算法的復雜度。

一、數據結構的選擇
1. 在列表中查找:

 對于已經排序的列表考慮用bisect模塊來實現查找元素,該模塊將使用二分查找實現

def find(seq, el) :  pos = bisect(seq, el)  if pos == 0 or ( pos == len(seq) and seq[-1] != el ) :    return -1  return pos - 1

而快速插入一個元素可以用:

 bisect.insort(list, element) 

這樣就插入元素并且不需要再次調用 sort() 來保序,要知道對于長list代價很高.

2. set代替列表:

 比如要對一個list進行去重,最容易想到的實現:

seq = ['a', 'a', 'b']res = []for i in seq:  if i not in res:    res.append(i)

顯然上面的實現的復雜度是O(n2),若改成:

seq = ['a', 'a', 'b']res = set(seq)

復雜度馬上降為O(n),當然這里假定set可以滿足后續使用。

另外,set的union,intersection,difference等操作要比列表的迭代快的多,因此如果涉及到求列表交集,并集或者差集等問題可以轉換為set來進行,平時使用的時候多注意下,特別當列表比較大的時候,性能的影響就更大。

3. 使用python的collections模塊替代內建容器類型:

collections有三種類型:

deque:增強功能的類似list類型
defaultdict:類似dict類型
namedtuple:類似tuple類型

       列表是基于數組實現的,而deque是基于雙鏈表的,所以后者在中間or前面插入元素,或者刪除元素都會快很多。

       defaultdict為新的鍵值添加了一個默認的工廠,可以避免編寫一個額外的測試來初始化映射條目,比dict.setdefault更高效,引用python文檔的一個例子:

#使用profile stats工具進行性能分析>>> from pbp.scripts.profiler import profile, stats>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3),... ('blue', 4), ('red', 1)]>>> @profile('defaultdict')... def faster():... d = defaultdict(list)... for k, v in s:... d[k].append(v)...>>> @profile('dict')... def slower():... d = {}... for k, v in s:... d.setdefault(k, []).append(v)...>>> slower(); faster()Optimization: Solutions[ 306 ]>>> stats['dict']{'stones': 16.587882671716077, 'memory': 396,'time': 0.35166311264038086}>>> stats['defaultdict']{'stones': 6.5733464259021686, 'memory': 552,'time': 0.13935494422912598}

可見性能提升了快3倍。defaultdict用一個list工廠作為參數,同樣可用于內建類型,比如long等。

除了實現的算法、架構之外,python提倡簡單、優雅。所以正確的語法實踐又很有必要,這樣才會寫出優雅易于閱讀的代碼。

二、語法最佳實踐
字符串操作:優于python字符串對象是不可改變的,因此對任何字符串的操作如拼接,修改等都將產生一個新的字符串對象,而不是基于原字符串,因此這種持續的 copy會在一定程度上影響Python的性能:
        (1)用join代替 '+' 操作符,后者有copy開銷;

        (2)同時當對字符串可以使用正則表達式或者內置函數來處理的時候,選擇內置函數。如str.isalpha(),str.isdigit(),str.startswith((‘x', ‘yz')),str.endswith((‘x', ‘yz'))

        (3)字符格式化操作優于直接串聯讀?。?/p>

     str = "%s%s%s%s" % (a, b, c, d)  # efficient
     str = "" + a + b + c + d + ""  # slow

2. 善用list comprehension(列表解析)  & generator(生成器) & decorators(裝飾器),熟悉itertools等模塊:

(1) 列表解析,我覺得是python2中最讓我印象深刻的特性,舉例1:

   >>> # the following is not so Pythonic    >>> numbers = range(10)   >>> i = 0    >>> evens = []    >>> while i < len(numbers):    >>>  if i %2 == 0: evens.append(i)    >>>  i += 1    >>> [0, 2, 4, 6, 8]    >>> # the good way to iterate a range, elegant and efficient   >>> evens = [ i for i in range(10) if i%2 == 0]    >>> [0, 2, 4, 6, 8]  

 

舉例2:

def _treament(pos, element):  return '%d: %s' % (pos, element)f = open('test.txt', 'r')if __name__ == '__main__':  #list comps 1  print sum(len(word) for line in f for word in line.split())  #list comps 2  print [(x + 1, y + 1) for x in range(3) for y in range(4)]  #func  print filter(lambda x: x % 2 == 0, range(10))  #list comps3  print [i for i in range(10) if i % 2 == 0]  #list comps4 pythonic  print [_treament(i, el) for i, el in enumerate(range(10))]output:24[(1, 1), (1, 2), (1, 3), (1, 4), (2, 1), (2, 2), (2, 3), (2, 4), (3, 1), (3, 2), (3, 3), (3, 4)][0, 2, 4, 6, 8][0, 2, 4, 6, 8]['0: 0', '1: 1', '2: 2', '3: 3', '4: 4', '5: 5', '6: 6', '7: 7', '8: 8', '9: 9']

沒錯,就是這么優雅簡單。

   (2) 生成器表達式在python2.2引入,它使用'lazy evaluation'思想,因此在使用內存上更有效。引用python核心編程中計算文件中最長的行的例子:

f = open('/etc/motd, 'r')longest = max(len(x.strip()) for x in f)f.close()return longest

這種實現簡潔而且不需要把文件文件所有行讀入內存。

 (3) python在2.4引入裝飾器,又是一個讓人興奮的特性,簡單來說它使得函數和方法封裝(接收一個函數并返回增強版本的函數)更容易閱讀、理解。'@'符號是裝飾器語法,你可以裝飾一個函數,記住調用結果供后續使用,這種技術被稱為memoization的,下面是用裝飾器完成一個cache功能:

import timeimport hashlibimport picklefrom itertools import chaincache = {}def is_obsolete(entry, duration):  return time.time() - entry['time'] > durationdef compute_key(function, args, kw):  #序列化/反序列化一個對象,這里是用pickle模塊對函數和參數對象進行序列化為一個hash值  key = pickle.dumps((function.func_name, args, kw))  #hashlib是一個提供MD5和sh1的一個庫,該結果保存在一個全局字典中  return hashlib.sha1(key).hexdigest()def memoize(duration=10):  def _memoize(function):    def __memoize(*args, **kw):      key = compute_key(function, args, kw)      # do we have it already      if (key in cache and        not is_obsolete(cache[key], duration)):        print 'we got a winner'        return cache[key]['value']      # computing      result = function(*args, **kw)      # storing the result      cache[key] = {'value': result,-              'time': time.time()}      return result    return __memoize  return _memoize@memoize()def very_very_complex_stuff(a, b, c):  return a + b + cprint very_very_complex_stuff(2, 2, 2)print very_very_complex_stuff(2, 2, 2)@memoize(1)def very_very_complex_stuff(a, b):  return a + bprint very_very_complex_stuff(2, 2)time.sleep(2)print very_very_complex_stuff(2, 2)

運行結果:

6we got a winner644

 

裝飾器在很多場景用到,比如參數檢查、鎖同步、單元測試框架等,有興趣的人可以自己進一步學習。

3.  善用python強大的自省能力(屬性和描述符):自從使用了python,真的是驚訝原來自省可以做的這么強大簡單,關于這個話題,限于內容比較多,這里就不贅述,后續有時間單獨做一個總結,學習python必須對其自省好好理解。

三、 編碼小技巧
1、在python3之前版本使用xrange代替range,因為range()直接返回完整的元素列表而xrange()在序列中每次調用只產生一個整數元素,開銷小。(在python3中xrange不再存在,里面range提供一個可以 遍歷任意長度的范圍的iterator)
2、if done is not None比語句if done != None更快;
3、盡量使用"in"操作符,簡潔而快速: for i in seq: print i
4、'x < y < z'代替'x < y and y < z';
5、while 1要比while True更快, 因為前者是單步運算,后者還需要計算;
6、盡量使用build-in的函數,因為這些函數往往很高效,比如add(a,b)要優于a+b;
7、在耗時較多的循環中,可以把函數的調用改為內聯的方式,內循環應該保持簡潔。
8、使用多重賦值來swap元素:

      x, y = y, x  # elegant and efficient

 而不是:

      temp = x 
      x = y 
      y = temp 

9. 三元操作符(python2.5后):V1 if X else V2,避免使用(X and V1) or V2,因為后者當V1=""時,就會有問題。

10. python之switch case實現:因為switch case語法完全可用if else代替,所以python就沒  有switch case語法,但是我們可以用dictionary或lamda實現:

switch case結構:

switch (var){  case v1: func1();  case v2: func2();  ...  case vN: funcN();  default: default_func();}dictionary實現:values = {      v1: func1,      v2: func2,      ...      vN: funcN,     }values.get(var, default_func)()lambda實現:{ '1': lambda: func1, '2': lambda: func2, '3': lambda: func3}[value]()

用try…catch來實現帶Default的情況,個人推薦使用dict的實現方法。

 這里只總結了一部分python的實踐方法,希望這些建議可以幫助到每一位使用python的同學,優化性能不是重點,高效解決問題,讓自己寫的代碼更加易于維護!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产美女高潮久久白浆| 国产精品v片在线观看不卡| 69影院欧美专区视频| 亚洲97在线观看| 日韩免费观看网站| 91久久久久久久久久久久久| 国产精品女主播视频| 亚洲欧洲日韩国产| 91精品在线观| 精品亚洲va在线va天堂资源站| 亚洲社区在线观看| 久久久人成影片一区二区三区观看| 亚洲乱码国产乱码精品精天堂| 日韩av大片免费看| 国产丝袜一区视频在线观看| 91香蕉国产在线观看| 亚洲激情第一页| 一本色道久久综合亚洲精品小说| 在线视频欧美日韩精品| 亚洲经典中文字幕| 久久久综合av| 96国产粉嫩美女| 国产亚洲激情在线| 成人激情视频网| 高清亚洲成在人网站天堂| 欧美日韩一区免费| 国内精品久久影院| 久久福利网址导航| 中日韩美女免费视频网站在线观看| 亚洲欧美福利视频| 日韩电影中文字幕在线观看| 国产精品久久久久免费a∨| 精品国产一区二区在线| 国产成人精品一区二区| 久久久久亚洲精品| 深夜福利亚洲导航| 中文字幕日韩欧美精品在线观看| 国产精品国产三级国产aⅴ9色| 欧美激情啊啊啊| 国产91精品久久久久久久| 疯狂做受xxxx欧美肥白少妇| 亚洲国产精品专区久久| 久久久久久综合网天天| 视频在线观看99| 亚洲欧洲自拍偷拍| 成人激情视频小说免费下载| 久久99精品久久久久久青青91| 92版电视剧仙鹤神针在线观看| 欧美日韩成人在线播放| 91国内在线视频| 国产精品美女999| 亚洲人a成www在线影院| 色老头一区二区三区在线观看| 国产精品综合不卡av| 免费91麻豆精品国产自产在线观看| 欧美老女人性生活| 久久久视频精品| 亚洲国产精品久久久| 亚洲欧美国产视频| 精品视频久久久久久久| 色偷偷av一区二区三区| 精品国产电影一区| 日韩欧美精品在线观看| 美日韩丰满少妇在线观看| 日韩电影视频免费| 国产精品91视频| 日韩免费观看网站| 亚洲97在线观看| 日韩精品免费一线在线观看| 欧美激情精品久久久久| 欧美日韩中文字幕在线视频| 韩国视频理论视频久久| 国产盗摄xxxx视频xxx69| 国产主播喷水一区二区| 亚洲日本欧美中文幕| 国产精品欧美日韩久久| 国产suv精品一区二区三区88区| 中文字幕亚洲国产| 日韩精品视频免费专区在线播放| 黑人巨大精品欧美一区二区免费| 成人在线中文字幕| 国产欧美日韩精品丝袜高跟鞋| 国产精品久久久久久久久粉嫩av| 日韩中文综合网| 欧美激情成人在线视频| 日韩av免费一区| 亚洲欧美综合另类中字| 97精品一区二区视频在线观看| 亚洲成**性毛茸茸| 亚洲高清一区二| 亚洲天堂网站在线观看视频| 日韩av影片在线观看| 精品调教chinesegay| 午夜精品久久久久久久久久久久久| 国产精品91久久久| 色视频www在线播放国产成人| 在线视频欧美日韩精品| 青青草99啪国产免费| 国产日韩在线精品av| 韩国视频理论视频久久| 午夜精品久久久久久久久久久久久| 国产欧美婷婷中文| 日韩专区在线观看| 亚洲人成啪啪网站| 久久99精品久久久久久噜噜| 亚洲欧美资源在线| 色先锋久久影院av| 亚洲欧美国内爽妇网| 国产在线精品播放| 亚洲一级片在线看| 亚洲人成电影网站色| 青草青草久热精品视频在线网站| 国产suv精品一区二区| 国产香蕉一区二区三区在线视频| 欧美电影免费观看电视剧大全| 色综合久久悠悠| 中文字幕日韩专区| 国产一区二区三区欧美| 91sao在线观看国产| 久久久久久久爱| 亚洲欧美日本伦理| 91爱爱小视频k| 国内精品久久久久久久久| 亚洲在线www| 欧美日韩在线观看视频小说| 色婷婷久久av| 欧美xxxx做受欧美.88| 久久99国产精品久久久久久久久| 国产激情综合五月久久| 欧美亚洲午夜视频在线观看| 亚洲香蕉伊综合在人在线视看| 亚洲国产私拍精品国模在线观看| 欧美放荡办公室videos4k| 日韩动漫免费观看电视剧高清| 国产精品久久久久久久久影视| 国内精久久久久久久久久人| 91在线观看免费| 国产精品www网站| 日本一区二区在线免费播放| 欧美精品久久久久久久| 精品国内产的精品视频在线观看| 久久久久久久久爱| 一区二区三区四区在线观看视频| 亚洲欧美国产精品va在线观看| 欧美亚州一区二区三区| 在线激情影院一区| 国产精自产拍久久久久久蜜| 国内精品一区二区三区| 在线观看中文字幕亚洲| 一区二区三区四区视频| 精品亚洲精品福利线在观看| 欧美老女人性视频| 亚洲伊人一本大道中文字幕| 欧美美女15p| 成人黄色免费在线观看| 久久久国产在线视频| 亚洲国产精品电影在线观看| 精品国产91久久久| 国产精品网红福利| 欧美在线激情网| 中文字幕亚洲激情| 久久久999成人| 国产成人拍精品视频午夜网站| 欧美日韩中国免费专区在线看|