天天看點

Python程式設計者共性錯誤引言程式運作錯誤(Progmatic Mistakes)編碼錯誤(Coding Mistakes)程式設計錯誤(Programming mistakes)

引言

本篇部落格為譯文,翻譯自Learning Python一書作者總結的Python程式設計者共性錯誤一文,原文英文網址為

http://www.onlamp.com/pub/a/python/2004/02/05/learn_python.html

第一次翻譯這種技術部落格,有錯誤之處請及時指出。

注意:不是按照原文一字一句翻譯的,意譯,是以隻要保證技術細節對就行。

程式運作錯誤(Progmatic Mistakes)

在具體到具體程式文法之前,初學者可能遇到的錯誤,主要集中在運作程式可能會犯的一些錯誤。

在互動指令行輸入python代碼

差別系統指令行與python互動指令行的差別,在windows或linux系統指令行中輸入“python”,回車後進入python 互動指令行(interactive prompt),此時指令行以“>>>”開頭,可以輸入python代碼,不可以直接輸入ls,emac,vim等系統指令,當然此時也可以調用這些指令,但不能直接調用,要是用python的package,“import os.system”,之後才能調用;在python互動指令行也不能直接運作python檔案,在系統指令行可以,“python filename”即可,而在python互動指令行下,需要使用“import file”指令才能使用。

在檔案中必須使用print語句

在互動指令行自動列印變量或表達式結果,但是在以檔案形式運作python程式時(程式寫在代碼檔案裡),必須輸入print語句才能列印結果。

在Windows系統中注意自動擴充名

在Windows系統中使用記事本等編輯檔案中,預設儲存為txt檔案,此時使python解釋器無法運作python代碼,注意選擇儲存格式為all files,然後手動敲入檔案名加檔案擴充名,如“filename.py”,也可以使用特定的代碼編輯軟甲或內建開發環境。

Windows系統直接點選運作代碼檔案

Windows系統中輕按兩下運作代碼檔案,如果沒有input()等語句,則程式運作時會一閃而過,基本無法看到運作結果,此時,要在系統指令行下python filename.py或import module或在內建開發環境中運作程式。

import隻在第一次起作用

import語句用于導入其他子產品,但如果你一直在輸入程式,而沒有關閉互動指令行,此前import的子產品一直駐留在記憶體中,你對其他子產品的更改不會作用到目前輸入的程式中,需要重新載入(reload)子產品,具體調用reload函數,如“ reload(module)”

在互動指令行中空白行有意義

在檔案中,空白行沒有任何意義,被解釋器忽略,但是在互動指令行中,為了區分代碼塊是否完結,需要空白行來間隔其他代碼來表示,是以對于for,while,等代碼塊結束時,需要額外輸入至少一行空白行表示該代碼塊結束。

編碼錯誤(Coding Mistakes)

不要忘記冒号

if、while、for等複合語句需要加冒号。

初始化變量

在python中,隻有給一個變量指定一個值,才能在表達式中調用它,防止變量歧義問題,如預設指派到底該指派什麼0,None,“”,[] ?,這是因為python是非強類型語言,必須通過指派确定變量如何配置設定記憶體。

從第一列開始

頂層代碼,都從最左側第一列開始。

縮進一緻

避免空格與Tab混合進行縮進。

調用函數總是使用括号文法

調用函數,為函數名加括号。

在import時不要加擴充名或路徑

import時會在環境變量指定的路徑下查找,是以不需要指定路徑;import時不需要加檔案擴充名。

不要在python中輸入C代碼

  • if,for,while 語句中不要加括号。
  • 不要以分号結束語句
  • 在while循環測試中,不能出現指派語句

程式設計錯誤(Programming mistakes)

這部分設計資料類型、函數、子產品、類等錯誤。

檔案打開不調用子產品搜尋路徑

使用檔案打開函數時,不使用子產品搜尋的路徑,而是參數給出的絕對目前目錄相對路徑。

方法是類型特定的

list的方法不能用于strings類型資料;len函數可以通用于任何帶長度對象。

不可變類型不能原地改變

不可變類型如元祖、字元串不能原地改變。如

T = (1, 2, 3)
T[2] = 4 # Error           

使用簡單for循環代替while或range

當需要周遊序列對象是,直接使用for循環,而不是使用基于while或range的循環,避免使用range函數,除非必要,讓python自己處理索引,如

S = 'lumberjack'

for c in S: # simplest
    print(c)

for i in range(len(S)): # too much
    print(S[i])

i = 0
while i < len(S): # too much
    print(S[i])
    i += 1           

不要指望來自函數的結果改變對象

原地改變操作如list.append()和list.sort()改變對象,但是沒有傳回被修改的對象;如

mylist = mylist.append(X)           

mylist将會被指派為None而不是給修改的list。

D = {1:'a', 2:'b'}
for k in D.keys().sort():
    print(D[k])           

上面代碼出錯,因為sort()函數傳回None,不是序列變量不能進行循環周遊,正确的為

Ks = D.keys()
Ks.sort()
for k in Ks:
    print(D[k])           

轉換隻發生在數字類型之間

預設自動轉換隻發生在數字類型之間,如果在數字類型與字元串類型則不能轉換,這是因為非數字類型之間轉換無法确定轉為哪一種類型。

Cyclic資料結構可導緻循環

集合對象包含對自身的引用稱為cyclic object,python會列印為[ … ]當它發現對象存在循環時,而不是陷入無限循環。

指派産生引用,不是拷貝

這個python的核心概念。

L = [1, 2, 3]
M = ['M', L, 'Y']
print(M) # ['X', [1, 2, 3], 'Y']
L[1] = 0
print(M) # ['X', [1, 0, 3], 'Y']           

可以拷貝避免共享對象。

L = [1, 2, 3]
M = ['M', L[:], 'Y']
print(M) # ['X', [1, 2, 3], 'Y']
L[1] = 0
print(L) # [1, 0, 3]
print(M) # ['X', [1, 2, 3], 'Y']           

局部變量被靜态發現

python将函數内部指派的變量預設為局部變量,存在于函數範圍内,隻在函數運作時。python靜态發現局部變量。

X = 99
def func():
    print(X) # Does not yet exit
    X = 88   # Make X local in entire def

func() # Error!           

會報錯,編譯這段代碼時,python發現指派語句,X在函數内部局部變量,實際函數運作時,指派語句還沒執行,python産生未定義名稱錯誤(undefined name error)。

上述代碼是歧義的:你是要列印全局變量X,然後建立一個局部變量X,還是這是一個程式設計錯誤?如果你要列印全局變量X,應該用global聲明或通過子產品名調用。

預設或可變對象

預設參數被存儲一次,當def語句運作時,而不是每次調用,在改變可變對象時必須小心,如

def saver(x=[]):
    x.append(1)
    print(x)
saver([2]) # [2, 1], Default not used
saver() # [1], Default used
saver() # [1, 1], Grows on each call!
saver() # [1, 1, 1]           

改變上述行為,可以通過在函數開始處拷貝預設值或移動預設值表達式到函數體中,隻要保證指派代碼每次函數調用時執行即可。

def saver(x=None):
    if x is None: # No arg passed?
        x = []    # Changes new list
    x.append(1)
    print(x)
saver([2]) # [2, 1], Default not used
saver() # [1], Default used
saver() # [1], Doesn't grows now
saver() # [1]           

其他錯誤

  • 檔案從上到下讀取,是以非遞歸代碼調用在定義之下
  • reload不作用于from語句
  • 多繼承時從左至右,最左類繼承如果後面還有同名出現
  • 空except語句捕獲所有類型異常
  • Bunnies can be more dangerous than they seem(不知道如何翻譯)