• python 规范篇 如何合理使用 assert


    assert 的合理使用,可以增加代码的健壮度,同时也方便了程序出错时开发人员的定位排查。

    什么是 assert?

    Python 的 assert 语句,可以说是一个 debug 的好工具,主要用于测试一个条件是否满足。如果测试的条件满足,则什么也不做,相当于执行了 pass 语句;如果测试条件不满足,便会抛出异常 AssertionError,并返回具体的错误信息(optional)。它的具体语法是下面这样的:

    assert 1 == 2,  'assertion is wrong'
    

    它就相当于下面这两行代码:

    if __debug__:
        if not expression1: raise AssertionError(expression2)
    

    __debug__是一个常数,解释器开始运行时就已经决定了__debug__True,当运行时加上-O这个选项,__debug__False,导致所有的 assert 语句都失效。需要注意的是,直接对常数__debug__赋值是非法的。

    assert 的用法

    示例 1,用来检查折后价格,这个值必须大于等于 0、小于等于原来的价格,否则就抛出异常

    def apply_discount(price, discount):
        updated_price = price * (1 - discount)
        assert 0 <= updated_price <= price, 'price should be greater or equal to 0 and less or equal to original price'
        return updated_price
    

    示例 2,规定销售数目必须大于 0,这样就可以防止后台计算那些还未开卖的专栏的价格

    def calculate_average_price(total_sales, num_sales):
        assert num_sales > 0, 'number of sales should be greater than 0'
        return total_sales / num_sales
    

    示例 3,input必须是list

    def func(input):
        assert isinstance(input, list), 'input must be type of list'
        # 下面的操作都是基于前提:input必须是list
        if len(input) == 1:
            ...
        elif len(input) == 2:
            ...
        else:
            ... 
    

    assert错误示例

    示例 1,极客时间规定,必须是 admin 才能删除专栏,并且这个专栏课程必须存在。然而当执行时增加-O选项,会导致任何用户都可以删除专栏。

    def delete_course(user, course_id):
        assert user_is_admin(user), 'user must be admin'
        assert course_exist(course_id), 'course id must exist'
        delete(course_id)
    

    故,assert 即使被关闭也不能影响原本的代码功能和逻辑。可以采用下面这种写法。

    def delete_course(user, course_id):
        if not user_is_admin(user):
            raise Exception('user must be admin')
        if not course_exist(course_id):
            raise Exception('coursde id must exist')
        delete(course_id)  
    

    示例 2,如果你想打开一个文件,进行数据读取、处理等一系列操作,那么下面这样的写法,显然也是不正确的。

    def read_and_process(path):
        assert file_exist(path), 'file must exist'
        with open(path) as f:
          ...
    

    因为 assert 的使用,表明你强行指定了文件必须存在,但事实上在很多情况下,这个假设并不成立。另外,打开文件操作,也有可能触发其他的异常。所以,正确的做法是进行异常处理,用 try 和 except 来解决:

    def read_and_process(path):
        try:
            with open(path) as f:
                ...
        except Exception as e:
                ...  
    

    总的来说,assert 并不适用 run-time error 的检查。比如你试图打开一个文件,但文件不存在;再或者是你试图从网上下载一个东西,但中途断网了了等等,这些情况下,还是应该参照我们前面所讲的错误与异常的内容,进行正确处理。

  • 相关阅读:
    LeetCode 12. Integer to Roman
    个人博客09
    个人博客08
    人机交互之我的输入法
    学习进度条(第六周)
    《梦断代码》阅读笔记02
    个人博客07
    学习进度条(第五周)
    个人博客06
    个人博客05
  • 原文地址:https://www.cnblogs.com/hiyang/p/12634744.html
Copyright © 2020-2023  润新知