培養python思維(1)

對於Python新手來說,寫代碼很少考慮代碼的效率和簡潔性,因此容易造成代碼冗長、執行慢,這些都是需要改進的地方。本文是想通過幾個案列給新手一點啓發,怎樣寫python代碼更優雅。

一、與第三方庫相比,同樣強大的標準庫

標準庫itertools和collections仍然很少被初學者使用

itertools

如果你看到下面的任務:

list1 = range(1,10)
list2 = range(10,20)
for item1 in list1:
    for item2 in list2:
        print(item1*item2)

這是一個嵌套循環操作,爲提高代碼效率,完全可以用product()函數替代嵌套循環:

from itertools import product
list1 = range(1,10)
list2 = range(10,20)
for item1,item2 in product(list1, list2):
    print(item1*item2)

這兩段代碼的結果完全一樣,但使用標準庫函數明顯更加簡潔高效。itertools還有很多方便操作迭代對象的函數,比如:

  • count()函數會創建一個無限迭代器
  • cycle()函數會把傳入的序列無限重複下去
  • chain()可以把多個迭代對象串聯起來
  • group()函數可以把迭代其中相鄰的重複元素挑出來,放在一起

    有興趣可以詳細看看itertools庫的各種神奇函數

collections

新手對python集合模塊瞭解的可能並不多,你可能會遇到這樣的情形:

consolidated_list = [('a',1),('b',2),('c',3),('b',4)]
items_by_id = {}
for id_, item in consolidated_list:
    if id_ not in items_by_id: 
        items_by_id[id_] = []
    if id_ in items_by_id:
        items_by_id[id_].append(item)

上面代碼構建了一個字典,依次向字典中添加信息,如果某個鍵已經存在,則以某種方式修改該鍵的值;如果某個鍵不存在,則添加對應鍵值對。

這種算法非常常見,你可以用collects模塊的defaultdict()函數來實現同樣效果:

from collections import defaultdict
 
items_by_id = defaultdict(list)
consolidated_list = [('a',1),('b',2),('c',3),('b',4)]

for id_, item in consolidated_list:
    items_by_id[id_].append(item)

在此列中,defaultdict()接受一個list作爲參數,當鍵不存在時,則返回一個空列表作爲對應值。

有時候我們會遇到統計詞頻的案例,比如:

# 統計詞頻
colors = ['red', 'blue', 'red', 'green', 'blue', 'blue']
result = {}
for color in colors:
    if result.get(color)==None:
        result[color]=1
    else:
        result[color]+=1
print (result)
# 輸出 {'red': 2, 'blue': 3, 'green': 1}

完全可以用defaultdict()函數實現上面的計數功能:

colors = ['red', 'blue', 'red', 'green', 'blue', 'blue']
d = defaultdict(int)
for color in colors:
    d[color] += 1
print(d)

更簡單的方法用collections模塊的Counter()函數:

from collections import Counter
colors = ['red', 'blue', 'red', 'green', 'blue', 'blue']
c = Counter(colors)
print (dict(c))

對於備份文件,新人往往會用system模塊:

from  os import system
system("xcopy e:\\sample.csv  e:\\newfile\\")

其實shutil模塊更好用:

import shutil
shutil.copyfile('E:\\q.csv', 'e:\\movie\\q.csv')

因爲shutil會很詳細地報告錯誤和異常。

二、生成器

除非你的list十分複雜,並且頻繁調用,否則都建議使用生成器,因爲它非常節省內存,舉個例子:

def powers_of_two(max=20000):
    i = 0
    powers = []
    while 2**i < max:
        powers.append[2**i]
        i += 1
    return powers

對於使用次數少、佔據大量內存、且容易生成的數據,可以用生成器替代列表存儲:

from itertools import count, takewhile
def powers_of_two(max=20000):
    for index in takewhile(lambda i: 2**i < max, count(start=0)):
        yield 2**index

本文部分內容節選自Tony Flury在Quora的回答

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章