1. 程式人生 > 實用技巧 >你在濫用Python嗎?初學者常會遇到的5個情景

你在濫用Python嗎?初學者常會遇到的5個情景

Python擁有眾多學習者,可謂是如今許多程式設計初學者的首選語言。易學的語法、豐富的庫和大量的社群都是Python飛速發展的主要原因。

6年前,在我掌握了一系列Java之後接觸到Python時,經常發現自己在寫Python程式碼時腦子裡還想著Java。作為一個新手,我沒有充分利用Python的優點,甚至在某些情況下,我濫用了它。

現在,我仍然看到一些初學者在沒有先花時間閱讀最佳實踐和建議的情況下就開始用Python寫程式碼。為解決這個問題,我列出了下面5個濫用Python的情景,並給出了相關改進建議。

1. 使用列表時

列表允許儲存各種資料型別的元素且不限制大小,儘管這種靈活性使列表成為收集資料的首選,但實際上仍有一些使用和不使用它的最佳實踐情景。

在儲存具有相同性質(資料型別和含義)的元素時,應該使用列表。Python不會通過程式設計來限制這一點,在列表中儲存單個自然項讓開發人員的工作更輕鬆。開發人員很容易預測將來列表會有哪些項,並確信地編寫指令碼。

思考下面的物品列表。這個列表並不包含單一性質的專案,開發人員無法確定該列表是否包含房屋部件、尺寸或其他東西,因此他應該分別處理不同的專案:

list_of_things=['Door',2,'Window',True,[2.3,1.4])]

思考下面的水果列表和分數列表。從前兩個專案中,你很容易推斷出第一個列表會始終包含水果名字,而第二個列表始終包含分數值:

list_of_fruits=['apple','orange','pear','cherry','banana']list_of_scores=[80,98,50,55,100]

在儲存具有不同含義或資料型別的專案時,使用元組更合適。元組不具備在不建立新物件的情況下,提供儲存不受限專案的靈活性(因為元組是不可變的)。

2. 迭代連線字串時

在Python中所有東西都是物件,包括可變和不可變物件。每當更新分配給物件的值時,不可變物件需建立新物件,而可變物件則不需要。

假設你想在一個字串中生成整個字母表。因為字串是不可變物件,所以每當使用“+”運算子連線字串值時,就會得到一個新的物件。

one_line_alphabet=''forletter_indexinrange(ord('a'),ord('z')):one_line_alphabet+=chr(letter_index)

Join函式是連線字串的首選方法。使用join函式可將計算時間縮短約3倍。在我做的一項測試中,迭代連線100萬個字串值耗時0.135秒,若使用join( )函式則只需0.044秒。

small_letters=[chr(i)foriinrange(ord('a'),ord('z')+1)]single_line_alphabet=''.join(small_letters)

因此,需要連線字串列表時請使用join函式。若使用join函式連線幾個字串,這並不會直觀感受到效能的差異。若要連線幾個字串值,請使用.format而不是“+”運算子。例如:

name='John'surname='Doe'full_name='{name}{surname}'.format(namename=name,surnamesurname=surname)

3. 讀寫檔案時

若要使用Python讀寫檔案,首先需要用內建的open函式開啟檔案。開啟檔案,讀取或寫入內容以及關閉檔案。進行操作時,可能會出現一些問題,比如忘記關閉檔案和異常處理失敗。

操作完成後,若忘記關閉檔案會導致後續問題。比如,如果在寫入檔案後忘記關閉該檔案,那麼寫入操作將不會儲存至檔案中,並且在檔案仍然保持開啟狀態時,你將保留在計算機中分配的資源。如果在處理檔案時,沒有手動處理異常和錯誤,那麼檔案將保持開啟的狀態。

f=open(file='file.txt',mode='r')lines=f.readlines()...f.close()

建議在開啟檔案時使用with關鍵字。with是一個上下文管理器,它能封裝程式碼並能確保自動處理異常。比如,當你讀寫檔案時,with-body中可能出現的任何故障,都能自動處理異常,並且始終保持該檔案關閉。

withopen('file.txt')asf:read_data=f.read()...

如果跳過with時,你需要自己處理一切,關閉檔案和異常處理都得親自處理。with會讓你的生活更輕鬆,讓情況得以控制。

4. 跳過生成器時

在許多情景中,你需要生成一個值列表,稍後將在指令碼中使用這些值。比如,你需要為前100個數字生成所有3個數字的組合。

combinations=[]value=100foriinrange(value):forjinrange(value):forkinrange(value):combinations.append((i,j,k))

當執行的命令完成時,列表組合將包含1M元組,每個元組有3個整型值。這些值將儲存在記憶體中,直到被刪除。使用sys模組中的getobjectsize函式檢查物件大小,結果為8.29MB。

不再使用列表儲存值並將它們全部儲存至記憶體,可以建立一個生成器,每當你使用它時,將生成1個組合。這能減少記憶體消耗並提高執行速度。

defgenerate_combinations_of_three(value):foriinrange(value):forjinrange(value):forkinrange(value):yield(i,j,k)gen=generate_combinations_of_three(100)next(gen)#yields(0,0,0)next(gen)#yileds(0,0,1)...

所以,儘可能多地使用生成器。時刻牢記記憶體容量是有限的,並儘可能優化記憶體使用。請使用生成器,特別是在開發可伸縮的解決方案時。

5. 使用推導式時

有一些程式設計師,他任何用Python編寫程式碼都遵循Python之禪(The Zen of Python)的準則。如果是使用Python的新手,可能會傾向於誇大Python之禪的某些觀點,而在其他方面避重就輕。

這一點在逐漸瞭解推導式時最容易注意到——你傾向於翻譯推導式中的“每一個”迴圈。假設你有一個三維的數字矩陣,你很可能會想將其平面化。

matrix=[[[1,2,3],[4,5,6],[7,8,9]],[[10,20,30],[40,50,60],[70,80,90]]]

使用列表推導式,平面化過程如下:

flatten_list=[xforsub_matrixinmatrixforrowinsub_matrixforxinrow]

使用迴圈,平面化過程如下:

flatten_list=[]forsub_matrixinmatrix:forrowinsub_matrix:forxinrow:flatten_list.append(x)

列表式很酷,但可讀的程式碼更酷。不要試圖總是讓自己使用列表式,即使這樣做可能需要編寫更少的程式碼,也不會損失程式碼的可讀性。

圖源:unsplash

不論是否有程式設計經驗,每當嘗試使用一種新的程式語言時,請一定要抽出時間閱讀最佳實踐。每種程式語言都有其獨特之處,所以要確保在適當的場景合理地運用它們。

Python致力於幫助程式設計師更高效便捷地完成工作,我們不能忽視可能對程式碼生命期產生負面影響的小決策。請儘可能尋找更好的和最佳的解決方案,這是程式設計師的工作使命。