|
|
|
|
公众号矩阵

致命错误!Python开发者的7个崩溃瞬间

下文汇总了程序员(尤其是新手)可能犯的常见错误,以及该如何纠正这些错误,编写更好的、无错误的Python代码。让我们开始吧!

作者:读芯术来源:今日头条|2020-11-20 20:49

本文转载自公众号“读芯术”(ID:AI_Discovery)。

毫无疑问,Python是当今使用最为广泛的编程语言。它的语法简单且易读,也很容易上手。

但无论你经验多丰富,或是已使用过多少种语言,切换到Python时都不能保证非常顺利。具有面向对象编程背景的开发人员容易忽略Python的惯用特性,很可能会滥用编程结构,从而产生不可预见且很难捕捉的错误。更糟糕的是,大多数错误很难发现,可能在后续工作中造成麻烦。

下文汇总了程序员(尤其是新手)可能犯的常见错误,以及该如何纠正这些错误,编写更好的、无错误的Python代码。让我们开始吧!

编写过于风格化的代码

这是Python初学者的一个典型特征。为了编写类似高级伪英语的代码,他们最终在其代码库中添加了以下类型的代码段:

  1. if x == 1 or x == 2 

看起来似乎不错。这行代码的意思是变量x必须为1或2才能满足条件。但是,此类代码片段太过风格化,影响了可读性。下面的替代代码段很容易理解,该行代码检查值是否属于列表中的元素:

  1. if x in [1,2] 

不必要的比较运算符:None和零

具有Java背景的程序员知道需要进行多少次空值(null)检查(尤其是在Java 8之前的版本中)。因此,在Python中看到这样的比较运算符就不足为奇了:

  1. a == None b != None 

上述情况可以利用python的方式编写代码来增强可读性:

  1. a is None 
  2. b is not None 

同样值得注意的是,对于0,实际上并不需要在条件逻辑中使用比较运算符。0解释为false,而非零数字则视为true。

使用长链式条件位逻辑

在大多数语言(包括Swift,Java,Kotlin)中,可用以下方式编写某些比较逻辑:

  1. if a < b < c 

大多数语言不能在非关联优先级中使用相邻运算符,而Python则不同,Python可以链式赋值,如以下代码所示:

  1. if a < b < c 

因此,这样做可以避免按位运算符。

使用type()代替isinstance(),反之亦然

type和isinstance是Python中用于类型检查的两个广泛使用的内置函数。通常,新手开发人员会认为这两个函数很相似并互换使用。这可能引发无法预料的错误,因为type()和isinstance()具有一些细微的差异。

isinstance()函数用于检查对象是否是指定类的实例,同时还要注意继承。另一方面,type()仅检查引用类型是否相等,并丢弃子类型。因此,以下代码使用type()和isinstance()给出了不同的结果:

  1. class Vehicle: 
  2.     pass 
  3.  
  4. class Car(Vehicle): 
  5.     passisinstance(Car(), Vehicle) #returns True 
  6. type(Car()) == Vehicle # returns False 

同样,以下代码将布尔值视为int的实例(因为True和False基本上被视为1和0),但是使用type函数给出了不同的结果。

  1. type(True) == int # falseisinstance(True, int) # trueisinstance(False,int) # true 

因此,重要的是要了解Python的两个类型检查器函数之间的差异,并且不要彼此混淆。

混淆作用域中的局部变量和全局变量

Python中的作用域规则看起来相当简单,但很容易造成误解。例如,以下代码在函数内部使用全局变量:

  1. a = 10 
  2. def printMe(): 
  3.     print(a)printMe() # prints 10 

如果通过修改函数中的变量来稍微调整上述代码,就会抛出错误:

  1. a = 20 
  2. def printA(): 
  3.     print(a) 
  4.     a = 10print(a) # gives 20 
  5. printA() # gives error as a is referenced before assigned 

一旦在函数内部修改了全局变量,Python就会将其视为局部变量,从而覆盖全局变量。甚至赋值前的打印语句也没有执行。

为确保此类名称冲突不会导致错误,可以在局部函数内为全局变量附加global关键字。甚至最好将全局变量(如果确实需要使用)放在单独的类中,以便始终将全局变量与类名一起使用。

可变默认参数

在Python中,使用默认参数很常见,它可以避免在调用函数时出现一长串参数。列表、字典和集合是Python中的可变类型。设置默认值会导致意外结果,如下所示:

  1. def addToList(x, a=[]): 
  2.     a.append(x) 
  3.     return alistOne = addToList(5) 
  4. #prints [5]anotherList = addToList(10) 
  5. # [5, 10] 

如你所见,第二个列表包含先前添加的元素,因为函数中的可变默认参数将它们存储在各个状态之间。

Python中可变默认对象的问题表现在定义函数时会对其进行评估,这会导致可变值也保存先前的内容。为避免此类严重的错误,请将None设置为默认值,然后在函数内分配可变变量,如下所示:

  1. def addElement(x, a=None): 
  2.     if not a: 
  3.         a = [] 
  4.     a.append(x) 
  5.     return a 

忽略多重继承和方法解析顺序

致命错误!Python开发者的7个崩溃瞬间

图源:unsplash

与大多数语言不同,Python支持多重继承。即在具有继承的类中,方法和类变量将根据继承类时指定的顺序执行。初学者通常会忽略此概念,尤其是在仅使用单一继承的情况下。在下面的代码中,当调用C类的方法时,将使用超类B的相应方法:

  1. >>> class A(object): 
  2. ...     def me(self): 
  3.           print("class A") 
  4.  
  5. >>> class B(A): 
  6. ...     def me(self): 
  7.           print("class B") 
  8. class C(B, A): 
  9.    passc = C() 
  10. c.me() # prints class B 

Python中继承类的顺序很重要,它可用来解决这些问题。

Python虽简单,但小心不要与其他语言混淆了,这可能会导致奇怪的错误和程序崩溃。希望上述的总结可以帮你理清概念,编写更稳定的Python代码。

【责任编辑:赵宁宁 TEL:(010)68476606】

点赞 0
分享:
大家都在看
猜你喜欢

订阅专栏+更多

云原生架构实践

云原生架构实践

新技术引领移动互联网进入急速赛道
共3章 | KaliArch

29人订阅学习

数据中心和VPDN网络建设案例

数据中心和VPDN网络建设案例

漫画+案例
共20章 | 捷哥CCIE

193人订阅学习

搭建数据中心实验Lab

搭建数据中心实验Lab

实验平台Datacenter
共5章 | ITGO(老曾)

119人订阅学习

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊

51CTO服务号

51CTO官微