欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

python編碼最佳實踐之總結(jié)

系統(tǒng) 1716 0

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

?工作中很多同事都在用python,但往往很少有人關(guān)注它的性能和慣用法,一般都是現(xiàn)學現(xiàn)用,畢竟python不是我們的主要語言,我們一般只是使用它來做一些系統(tǒng)管理的工作。但是我們?yōu)槭裁床蛔龅母媚兀縫ython 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鼓勵使用一種最優(yōu)的方法去完成一件事,這也是和ruby等的一個差異。所以一種好的python編寫習慣個人認為很重要,本文就重點從性能角度出發(fā)對python的一些慣用法做一個簡單總結(jié),希望對大家有用~

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

一、數(shù)據(jù)結(jié)構(gòu)的選擇
1. 在列表中查找:

?對于已經(jīng)排序的列表考慮用bisect模塊來實現(xiàn)查找元素,該模塊將使用二分查找實現(xiàn)

            
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) 

          

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

2. set代替列表:

?比如要對一個list進行去重,最容易想到的實現(xiàn):

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

          

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

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

          

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

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

3. 使用python的collections模塊替代內(nèi)建容器類型:

collections有三種類型:

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

?????? 列表是基于數(shù)組實現(xiàn)的,而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工廠作為參數(shù),同樣可用于內(nèi)建類型,比如long等。

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

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

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

??????? (3)字符格式化操作優(yōu)于直接串聯(lián)讀?。?

???? 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']


          

沒錯,就是這么優(yōu)雅簡單。

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

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

          

這種實現(xiàn)簡潔而且不需要把文件文件所有行讀入內(nèi)存。

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

            
import time
import hashlib
import pickle
from itertools import chain
cache = {}
def is_obsolete(entry, duration):
  return time.time() - entry['time'] > duration

def compute_key(function, args, kw):
  #序列化/反序列化一個對象,這里是用pickle模塊對函數(shù)和參數(shù)對象進行序列化為一個hash值
  key = pickle.dumps((function.func_name, args, kw))
  #hashlib是一個提供MD5和sh1的一個庫,該結(jié)果保存在一個全局字典中
  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 + c

print 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 + b

print very_very_complex_stuff(2, 2)
time.sleep(2)
print very_very_complex_stuff(2, 2)


          

運行結(jié)果:

            
6

we got a winner

6

4

4

          

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

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

三、 編碼小技巧
1、在python3之前版本使用xrange代替range,因為range()直接返回完整的元素列表而xrange()在序列中每次調(diào)用只產(chǎn)生一個整數(shù)元素,開銷小。(在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的函數(shù),因為這些函數(shù)往往很高效,比如add(a,b)要優(yōu)于a+b;
7、在耗時較多的循環(huán)中,可以把函數(shù)的調(diào)用改為內(nèi)聯(lián)的方式,內(nèi)循環(huán)應該保持簡潔。
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實現(xiàn):因為switch case語法完全可用if else代替,所以python就沒? 有switch case語法,但是我們可以用dictionary或lamda實現(xiàn):

switch case結(jié)構(gòu):

            
switch (var)
{
  case v1: func1();
  case v2: func2();
  ...
  case vN: funcN();
  default: default_func();
}
dictionary實現(xiàn):

values = {
      v1: func1,
      v2: func2,
      ...
      vN: funcN,
     }
values.get(var, default_func)()
lambda實現(xiàn):

{
 '1': lambda: func1,
 '2': lambda: func2,
 '3': lambda: func3
}[value]()


          

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

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


更多文章、技術(shù)交流、商務合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!??!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 99草在线观看 | 日本一区二区三区四区高清视频 | 成人情趣视频 | 日本午夜免费无码片三汲大片 | 国产精品1区2区3区 另类视频综合 | 欧美日韩xxx | 成人精品久久 | 国产三级在线观看视频 | 午夜黄色大片 | 亚洲欧美在线精品一区二区 | 男女网| 天天操天天插天天干 | 桃花综合| 北条麻妃国产九九九精品小说 | 国产深夜福利在线观看网站 | 国产亚洲精品日韩香蕉网 | 久久久999 | 99热在线播放 | 久久综合婷婷香五月 | 九九re6精品视频在线观看 | 亚洲婷婷在线 | 亚洲欧美在线观看一区二区 | 牛和人交videos欧美冫3d | 午夜视频网 | 久草在钱 | 日本在线黄 | 天天色天天射天天操 | 色人阁久久 | 日本亚洲国产精品久久 | 国产成人免费永久播放视频平台 | 欧美日韩性高爱潮视频 | 国产视频导航 | 日韩免费在线视频 | 久久久精彩视频 | 奇米第四色在线观看 | 亚洲av毛片久久久久 | 免费啪视频在线观看免费的 | 中文欧美日韩 | 欧美黑人激情 | 久久久9999久久精品小说 | 精品无码国产一区二区日本 |