1.什么是assert?
相信很多小伙伴在平时写代码时,肯定多少会看到断言assert语句的存在。但是,日常coding过程中,小伙伴们最常用的调试方法就是print大法啦。虽然我们在学习编程语言时,会学习到assert语法。但是,实际写代码时经常忘记使用这个“不起眼”的小方法,从而导致代码写得不够健壮。事实上,如果我们能在业务代码中将这个“不起眼”的小方法用好,也会便于我们调试代码。
上面啰啰嗦嗦说了一大堆,也没说清楚啥是assert?其实,assert语句是调试python程序的好工具,它主要用来测试一个条件是否满足。如果测试条件成立,则啥也不做;如果测试条件不成立,则会抛出AssertionError异常,并返回具体的错误信息。其他程序语言中也会有类似的断言语句,感兴趣的小伙伴可以自行百度一下。下面以一个简单的程序来演示assert语句是如何使用的:
assert 1 == 2
上面一行简单的代码,它相当于下面三行代码:
if __debug__: if not expression: raise AssertionError
再来看看assert expression1, expression2的形式是如何使用的,如下例所示:
assert 1 == 2, 'assert is wrong'
上面一行简单的代码,它相当于下面三行代码:
if __debug__: if not expression1: raise AssertionError(expression2)
上面两个简单的示例代码中,__debug__是一个常数,如果python程序执行时附带了-O选项,那么python程序中所有的assert语句都会失效,即__debug__的值为False;反之,__debug__则为True。
值得注意的是:如果直接对__debug__进行赋值是非法的,因为它的值在解释器开始运行时就已经决定了,程序运行过程中无法改变。此外,不要在使用assert语句时加入括号,不要加括号!!不要加括号!!!
2.assert的用法
通过上面一节的学习,相信小伙伴们已经对assert的基本语法有了基本了解。接下来通过一个实际应用的例子,具体看看assert语句在python中的用法,并弄清楚assert的使用场景。
假设一个电商平台正在进行打折促销活动,所以后端需要写一个apply_discount()函数,要求输入原来的价格和折扣,输出结果是打折后价格。因此,我们大致可以写出如下代码:
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
在上面的apply_discount()函数中,我们加入了一个assert语句,用来检测打折后商品的价格。打折后的价格应该大于等于0、小于等于原价,否则程序就抛出异常。下面测试一下上面写的函数,测试结果如下所示:
当discount是0.2时,输出80,一切正常。但是,当discount是2时,程序将会抛出异常。因此,如果我们修改相关代码或者加入新功能导致discount值异常时,测试时就会很容易定位问题。assert的加入,可以有效预防bug的发生,提高代码的健壮性。在实际开发中,assert还有一些很常见的用法,如下面的场景:
def func(input): assert isinstance(input, list), "input must be type of list" if len(input) == 1: # ... elif len(input) == 2: # ... else: # ...
函数func()中的所有操作都是基于输入参数必须是列表类型这个前提,此时就很有必要在开头加一句assert的检查,防止程序出错。
3.assert错误示例
经过前面的一波安利后,相信很多小伙伴都想在代码中尝试一下了。温馨提示:assert虽然很多地方都可以使用,但是也要注意使用场合。下面以一个场景举例:小王开了一家淘宝店,由于最近上新了一些新品。因此,需要删除一些上线时间较长的商品。于是,作为一名码农的CurryCoder便写出如下删除商品的函数:
def delete_item(user, item_id): assert user_is_xiaowang(user), "user must be xiaowang" assert item_exist(item_id), "item id must exist" delete(item_id)
客户小王要求:只有小王自己才有删除商品的资格,而且这个商品必须存在。
CurryCoder刚接到这个需求时,简单分析了一下需求就写出了上面的函数。但是,仔细分析后我们会发现上面的代码从功能上来说是对的,但是需要注意assert的检查是可以关闭的。当运行python程序,加入-O选项时就会让assert语句失效。因此,一旦assert的检查被关闭,user_is_xiaowang()和item_exist()这两个函数就不会执行。结果就会导致任何人都可以来删除商品,而且不管商品是否存在都可以被强制执行。所以,正确的做法是使用条件语句进行相应的检查,并抛出合理的异常。
def delete_item(user, item_id): if not user_is_xiaowang(user): raise Exception("user must be xiaowang") if not item_exist(item_id): raise Exception("item id must exist") delete(item_id)
4.总结
(1).assert语句通常用来对代码进行必要的自我检查,表明你很确定这种情况一定会发生或者一定不会发生。
(2).值得注意的是:使用assert时,一定不要加括号,否则会报错!
(3).代码中的assert语句,可以在运行python程序时通过-O选项进行去使能。
(4).不能乱用assert,很多情况下,程序中出现的不同情况都是意料之中的,需要我们用不同的方法去处理,此时用条件语句进行判断更合适。对应程序中的一些run-time error,请使用异常进行处理。