毫無疑問,Python是當今使用最爲普遍的編程語言。它的語法簡單且易讀,也很容易上手。python
但不管你經驗多豐富,或是已使用過多少種語言,切換到Python時都不能保證很是順利。具備面向對象編程背景的開發人員容易忽略Python的慣用特性,極可能會濫用編程結構,從而產生不可預見且很難捕捉的錯誤。更糟糕的是,大多數錯誤很難發現,可能在後續工做中形成麻煩。程序員
不少人學習python,不知道從何學起。web
不少人學習python,掌握了基本語法事後,不知道在哪裏尋找案例上手。編程
不少已經作案例的人,殊不知道如何去學習更加高深的知識。app
那麼針對這三類人,我給你們提供一個好的學習平臺,免費領取視頻教程,電子書籍,以及課程的源代碼!??¤編程語言
QQ羣:1057034340函數
下文彙總了程序員(尤爲是新手)可能犯的常見錯誤,以及該如何糾正這些錯誤,編寫更好的、無錯誤的Python代碼。讓咱們開始吧!學習
編寫過於風格化的代碼ui
這是Python初學者的一個典型特徵。爲了編寫相似高級僞英語的代碼,他們最終在其代碼庫中添加了如下類型的代碼段:spa
if x == 1 or x == 2
看起來彷佛不錯。這行代碼的意思是變量x必須爲1或2才能知足條件。可是,此類代碼片斷太過風格化,影響了可讀性。下面的替代代碼段很容易理解,該行代碼檢查值是否屬於列表中的元素:
if x in [1,2]
沒必要要的比較運算符:None和零
具備Java背景的程序員知道須要進行多少次空值(null)檢查(尤爲是在Java 8以前的版本中)。所以,在Python中看到這樣的比較運算符就不足爲奇了:
a == None b != None
上述狀況能夠利用python的方式編寫代碼來加強可讀性:
a is None
b is not None
一樣值得注意的是,對於0,實際上並不須要在條件邏輯中使用比較運算符。0解釋爲false,而非零數字則視爲true。
使用長鏈式條件位邏輯
在大多數語言(包括Swift,Java,Kotlin)中,可用如下方式編寫某些比較邏輯:
if a < b < c
大多數語言不能在非關聯優先級中使用相鄰運算符,而Python則不一樣,Python能夠鏈式賦值,如如下代碼所示:
if a < b < c
所以,這樣作能夠避免按位運算符。
使用type()代替isinstance(),反之亦然
type和isinstance是Python中用於類型檢查的兩個普遍使用的內置函數。一般,新手開發人員會認爲這兩個函數很類似並互換使用。這可能引起沒法預料的錯誤,由於type()和isinstance()具備一些細微的差別。
isinstance()函數用於檢查對象是不是指定類的實例,同時還要注意繼承。另外一方面,type()僅檢查引用類型是否相等,並丟棄子類型。所以,如下代碼使用type()和isinstance()給出了不一樣的結果:
class Vehicle:
pass
class Car(Vehicle):
passisinstance(Car(), Vehicle) #returns True
type(Car()) == Vehicle # returns False
一樣,如下代碼將布爾值視爲int的實例(由於True和False基本上被視爲1和0),可是使用type函數給出了不一樣的結果。
type(True) == int # falseisinstance(True, int) # trueisinstance(False,int) # true
所以,重要的是要了解Python的兩個類型檢查器函數之間的差別,而且不要彼此混淆。
混淆做用域中的局部變量和全局變量
Python中的做用域規則看起來至關簡單,但很容易形成誤解。例如,如下代碼在函數內部使用全局變量:
a = 10
def printMe():
print(a)printMe() # prints 10
若是經過修改函數中的變量來稍微調整上述代碼,就會拋出錯誤:
a = 20
def printA():
print(a)
a = 10print(a) # gives 20
printA() # gives error as a is referenced before assigned
一旦在函數內部修改了全局變量,Python就會將其視爲局部變量,從而覆蓋全局變量。甚至賦值前的打印語句也沒有執行。
爲確保此類名稱衝突不會致使錯誤,能夠在局部函數內爲全局變量附加global關鍵字。甚至最好將全局變量(若是確實須要使用)放在單獨的類中,以便始終將全局變量與類名一塊兒使用。
可變默認參數
在Python中,使用默認參數很常見,它能夠避免在調用函數時出現一長串參數。列表、字典和集合是Python中的可變類型。設置默認值會致使意外結果,以下所示:
def addToList(x, a=[]):
a.append(x)
return alistOne = addToList(5)
#prints [5]anotherList = addToList(10)
# [5, 10]
如你所見,第二個列表包含先前添加的元素,由於函數中的可變默認參數將它們存儲在各個狀態之間。
Python中可變默認對象的問題表如今定義函數時會對其進行評估,這會致使可變值也保存先前的內容。爲避免此類嚴重的錯誤,請將None設置爲默認值,而後在函數內分配可變變量,以下所示:
def addElement(x, a=None):
if not a:
a = []
a.append(x)
return a
忽略多重繼承和方法解析順序
圖源:unsplash
與大多數語言不一樣,Python支持多重繼承。即在具備繼承的類中,方法和類變量將根據繼承類時指定的順序執行。初學者一般會忽略此概念,尤爲是在僅使用單一繼承的狀況下。在下面的代碼中,當調用C類的方法時,將使用超類B的相應方法:
>>> class A(object):
... def me(self):
print("class A")
>>> class B(A):
... def me(self):
print("class B")
class C(B, A):
passc = C()
c.me() # prints class B
Python中繼承類的順序很重要,它可用來解決這些問題。
Python雖簡單,但當心不要與其餘語言混淆了,這可能會致使奇怪的錯誤和程序崩潰。但願上述的總結能夠幫你理清概念,編寫更穩定的Python代碼。