1. 程式人生 > 其它 >Quora千贊回答,python新手應該避免哪些坑

Quora千贊回答,python新手應該避免哪些坑

技術標籤:python程式語言資料分析資料視覺化生成器

對於Python新手來說,寫程式碼很少考慮程式碼的效率和簡潔性,因此容易造成程式碼冗長、執行慢,這些都是需要改進的地方。

本文是想通過幾個案列給新手一點啟發,怎樣寫python程式碼更優雅。

新人躺坑之一:不喜歡使用高階資料結構

sets(集合)

很多新手忽視sets(集合)和tuple(元組)的強大之處

例如,取兩個列表交集:

def common_elements(list1, list2):    
    common=[]    
    for item1 in list1:                
        if item1 in list2:            
            common.append(item1)、
    returncommon

這樣寫會更好:

defcommon_elements(list1,list2):    common=set(list1).interp(set(list2))    return list(common)

dic(字典)

新手列舉(訪問和取出)字典的鍵和對應值,認為對應值必須通過鍵來訪問,往往會這樣做:

my_dict = {'a':1,'b':2}
for key in my_dict:        
    print(key, my_dict[key])

有一個更優雅的方法可以實現:

my_dict = {'a':1,'b':2}
    for key, value in my_dict.items():    
    print(key, value)

對大部分專案來說,這樣寫會更加有效率。

tuple(元組)

元組一旦建立就無法更改元素,看似沒有什麼用處,其實元組的作用大著呢!很多函式方法都會返回元組,比如enumerate()dict.items(),並且可以在函式中使用元組,返回多個值。

還能夠很方便地從元組中提取資訊:

a,b = ('cat','dog')

上面元組中有兩個元素,分別被賦給a,b。如果有多個值,同樣可以提取:

a,b,c = ('cat','dog','tiger')
print(a,b,c)

提取首、尾兩個元素:

first,*_,end = (1,2,3,4,5,6)print(first,end)

輸出:1、6

提取首、中、尾三部分:

first,*middle,end = (1,2,3,4,5,6)print(first,middle,end)

輸出:1、[2, 3, 4, 5]、6

元組還可以用來交換變數:

(a,b,c) = (c,a,b)

上面a變成之前的c,b變成之前的a,c變成之前的b

元組也能作為字典的鍵,所以如果你需要儲存資料,可以使用帶有元組鍵的字典,比如說經緯度資料。

新人躺坑之二:不喜歡使用上下文管理器

新手可能會習慣這樣進行讀取檔案操作:

if os.path.exists(data_file_path):    
    data_file = open(data_file_path,'r')
else:
    raiseOSERROR
print(data_file.read())
data.close()

這樣寫會有幾個明顯的問題:

  • 可能出現檔案存在,但檔案被佔用,無法讀取的情況

  • 可能出現檔案可以被讀取,但操作檔案物件出現報錯的情況

  • 可能出現忘記關閉檔案的情況

如果使用with...語句,問題就迎刃而解了:

with open(data_file_path,'r') as data_file:    print(data_file.read)

這樣可以捕獲任何開啟檔案或處理資料時的異常情況,並且在任務處理完後自動關閉檔案。

python初學者可能不太瞭解上下文管理器的神奇之處,它真的能帶來巨大的便利。

更多關於python檔案讀寫和上下文管理器的使用,可以看下面的文章

新人躺坑之三:不喜歡使用標準庫

標準庫itertoolscollections仍然很少被初學者使用

itertools

如果你看到下面的任務:

list1 = range(1,10)
list2 = range(10,20)
for item1 in list1:
    for item2 in list1:
        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("xcopye:\\sample.csve:\\newfile\\")

其實shutil模組更好用:

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

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

新人躺坑之四:不喜歡使用異常處理

無論老手新手都應該在寫程式碼的時候進行異常處理操作,這樣可以使程式碼更加健壯。

異常處理一般會用try...except語句,具體使用方法可見:

新人躺坑之五:不喜歡使用生成器

除非你的list十分複雜,並且頻繁呼叫,否則都建議使用生成器,因為它非常節省記憶體,舉個例子:

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

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

fromitertoolsimportcount,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的回答,節選部分內容

福利時間:

推薦給大家一本比較不錯的python資料分析教程:《利用python進行資料分析》

該書內容詳細講解了如何利用python進行資料分析,並且有視覺化部分的講解。

想要PDF版本的小夥伴,在公眾號後臺回覆:資料分析

END


往期精選

geopandas,python畫地圖這麼簡單!

最全資料科學小抄,趕緊收藏吧!

教你如何使用Python製作酷炫二維碼

numba,讓python飛起來!
100行python程式碼爬取豆瓣《哪吒》短評

教你如何使用Python下載全網視訊

小白如何入門Python爬蟲

那些不為人知的優秀視覺化庫

Python機器學習·微教程

小白入門Python資料科學全教程

什麼是matplotlib?

一文搞懂python匿名函式

一文讀懂Python的map、reduce函式

一文搞懂python迭代器和生成器

Python大資料分析

data creatvalue

長按二維碼關注