毫无疑问,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代码。