专栏首页机器之心Python 初学者常犯的5个错误,布尔型竟是整型的子类

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

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

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

1. 可变的缺省参数

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

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

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

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

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

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

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

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

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

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

正确的代码要改成:

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

3. 使用 isinstance 代替 type

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

def which_number_type(num):
    if isinstance(num, int):
        print('Integer')
    else:
        raise TypeError('Not an integer')

which_number(False)  # prints 'Integer', which is incorrect

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

4. 不必要的 lambda 表达式

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

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

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

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

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

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

错误的例子:

class SitesManager(object):
    def get_image_tracking_code(self):
        raise NotImplemented

正确表达方法应该是:

class SitesManager(object):
    def get_image_tracking_code(self):
        raise NotImplementedError

本文分享自微信公众号 - 机器之心(almosthuman2014)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-08-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 资源 | 《Deep Learning》中文印前版开放下载,让我们向译者致敬

    选自GitHub 机器之心整理 参与:蒋思源 《Deep Learning》中文版(印前版)正式发布。这本书适合于各类读者,尤其是学习机器学习的本科或研究生、深...

    机器之心
  • 凭此知识树,从零入门SLAM

    SLAM 是 Simultaneous Localization And Mapping 的 缩写,一般翻译为:同时定位与建图、同时定位与地图构建。

    机器之心
  • 学界 | Bengio等提出稀疏注意力回溯:长期依赖关系建模的更一般化机制

    人类对与当前心理状态相关的很久之前的事件有很强的记忆能力(Ciaramelli et al., 2008)。大多数关于记忆的实验和理论分析都集中在理解形成记忆和...

    机器之心
  • Meltdown、Spectre攻击---CPU乱序执行和预测执行导致的安全问题

    俄亥俄州立大学计算机安全实验室 ? 乱序执行(Out-of-Order Execution) [1] 和预测执行(Speculative Execution) ...

    安智客
  • package http

    要管理代理、TLS配置、keep-alive、压缩和其他设置,创建一个Transport:

    李海彬
  • 带你构建你的的第一个Python和Django应用程序

    群内不定时分享干货,包括最新的python企业案例学习资料和零基础入门教程,欢迎初学和进阶中的小伙伴入群学习交流 ? 您以前可能听说过Python,特别是如果您...

    企鹅号小编
  • 【算法】猴子大王

    一群猴子排成一圈,按1,2,…,n依次编号。然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,在把它踢出去…,如此不停的进行下去,直到...

    苦咖啡
  • java学习|创建springboot工程

    在上篇整理篇中我们有聊到,以后的学习篇,我们会分阶段来写,让基础的同学能跟着练练基础,同时又能看到这个知识点的扩展,今天我们就从搭建web工程开始一步一步的往...

    微笑的小小刀
  • PDF.NET数据开发框架实体类操作实例

    本篇是 PDF.NET数据开发框架实体类操作实例(MySQL) 的姊妹篇,两者使用了同一个测试程序,不同的只是使用的类库和数据库不同,下面说说具体的使用过程。 ...

    用户1177503
  • 源目的IP和端口都相同的连接出现的原因

    线上遇到了一个比较特殊的连接,它的源目的IP和端口完全相同,复现的场景是:同一个机器上的两个模块A和B通信,A模块会向B模块的监听套接字发起连接请求,B模块重启...

    李海彬

扫码关注云+社区

领取腾讯云代金券