Python 初学者常犯的5个错误,布尔型竟是整型的子类

开发 开发工具 后端
Python 是一种神奇的语言,看似简单便捷,但总会有一些意想不到的惊喜在等着我们。比如说,assert 在正式环境下根本不会运行,isinstance(False, int) 竟然输出 True。

Python 是一种高级的动态编程语言,它以易于使用著名。目前 Python 社区已经非常完善了,近几年它的发展尤为迅猛。但是易于使用同样能带来一些坏处,即易于误用。在本文中,作者列举了 5 个初学者常犯的错误,希望它们能帮助初学者写更加正确与优美的代码。

[[275217]]

1. 可变的缺省参数

Python 中的缺省参数会在执行函数定义时计算一次,这表示在函数完成定义后该表达式只执行一次,因此缺省值可以用于后续的每一次调用。如果我们令缺省参数为可变的,例如列表或字典等,那么对于将来所有的调用,该参数都是一直保留且可变的。

如下为不正确的表达方式,如果我们第一次调用 add_item 增加「a」时,items=[『a』]。当我们第二次调用 add_item 增加「b」时,由于定义中的 items=[] 只在初始化的时候运行一次,因此这时的 items=[『a』, 『b』]。

尤其是当我们在调用 add_item 函数时没传入任何参数,那么 items 还是能保留以前记住的内容,相当于将以前的内容泄漏给了后续的调用。

  1. def add_item(new_item, items=[]): 
  2.     items.append(new_item) 

正确的表达方式应该是如下,在我们没传入 items 时应该要将它初始化为空白列表:

  1. def add_item(new_item, items=None): 
  2.     if items is None: 
  3.         items = [] 
  4.     items.append(new_item) 

2. 将 assert 声明语句作为保证条件

因为 assert 语句很容易检查一些条件是否满足或执行是否正确,开发者经常用它来检查某部分代码的有效性。但是当 Python 解释器调用时带了-O (optimize) flag,那么 assert 语句会从字节码中移除。所以,如果 assert 语句在面向用户验证的产品代码中,根本就不会执行,因为它可能会造成一些安全漏洞。

因此开发者应该只在测试中使用 assert 语句,不正确的示例如下:

  1. assert re.match(VALID_ADDRESS_REGEXP, email) is not None 

正确的代码要改成:

  1. if not re.match(VALID_ADDRESS_REGEXP, email): 
  2.     raise AssertionError 

3. 使用 isinstance 代替 type

type 和 isinstance 都能检查某个对象的类别是什么。但是它们间有非常重要的区别,isinstance 在解析目标类型时,它会关注继承关系,而 type 并不会。正因为这个区别,isinstance 在某些时候并不是我们所想的那样。例如以下案例:

  1. def which_number_type(num): 
  2.     if isinstance(num, int): 
  3.         print('Integer') 
  4.     else: 
  5.         raise TypeError('Not an integer') 
  6.  
  7. which_number(False)  # prints 'Integer', which is incorrect 

因为布尔类型的变量在 Python 中是 int 的子类,isinstance(num, int) 同样会得出 True,这并不是我们想要的。在特定的类别中,使用 type 可能更加正确。

4. 不必要的 lambda 表达式

函数在 Python 中是最常用的结构,我们能将函数赋值给某个变量,并将该变量作为参数传递给另外一个函数,这也是函数常见的用法。但这对于初学者或了解其它编程语言的开发者而言,这种传递方式是非常反直觉的。

一个比较常见的模式可以表示为:

  1. def request(self, method, **kwargs): 
  2.     # ... 
  3.     if method not in ("get", "post"): 
  4.         req.get_method = lambda: method.upper() 

上面采用匿名函数 lambda 的方式,最好可以改成以下:

  1. def request(self, method, **kwargs): 
  2.     # ... 
  3.     if method not in ("get", "post"): 
  4.         req.get_method = method.upper 
  5.     # ... 

5. NotImplemented错误

这种命名可能会使开发者感到困惑,NotImplementedError 是一种 exception 类,当派生类需要重写某个方法时,Python 应该触发这类错误。而 NotImplemented 是一个常量,它用于实现二进制操作。当我们触发 NotImplemented 时,Python 会给出「TypeError」的报错。

错误的例子:

  1. class SitesManager(object): 
  2.     def get_image_tracking_code(self): 
  3.         raise NotImplemented 

正确表达方法应该是:

  1. class SitesManager(object): 
  2.     def get_image_tracking_code(self): 
  3.         raise NotImplementedError 

原文链接:https://deepsource.io/blog/python-common-mistakes/

【本文是51CTO专栏机构“机器之心”的原创译文,微信公众号“机器之心( id: almosthuman2014)”】 

戳这里,看该作者更多好文

 

责任编辑:赵宁宁 来源: 51CTO专栏
相关推荐

2022-07-22 15:55:32

Python代码语言

2023-01-17 09:27:18

Python语言

2022-10-19 23:18:27

KubernetesPod错误

2020-09-06 08:19:11

Python编程语言开发

2024-03-11 18:17:18

Python字符串分隔符

2020-01-14 17:31:46

数据科学误区人工智能

2020-07-27 13:49:47

Python编程语言开发

2018-04-02 11:59:04

Linux命令ln

2020-03-02 14:20:46

PythonGitHub编程语言

2014-01-03 14:09:57

Git学习

2020-09-06 22:04:48

Python运算符开发

2014-03-12 10:11:57

Python设计模式

2020-03-01 14:57:47

Python编程函数

2011-07-04 14:14:54

java

2009-09-28 09:45:00

CCNA学习经验CCNA

2011-06-17 15:06:14

Qt

2022-10-10 15:28:45

负载均衡

2015-07-20 13:56:59

SDN

2010-03-10 17:09:26

Python语言

2011-04-08 15:07:40

C++
点赞
收藏

51CTO技术栈公众号