游戏开发工具

Python如何合理使用assert

讲完了 assert 的基本语法之后,本节通过一些实际应用的例子,给大家演示一下 assert 在 Python 中的用法,并明确 assert 的使用场景。

第一个例子,假设 C 语言中文网想做 VIP 促销活动,准备进行打折,现需要写一个 apply_discount() 函数,要求是,向该函数传入原来的价格和折扣力度,该函数返回打折后的价格。

apply_discount() 大致应该写成如下这样:

#price 为原价,discount 为折扣力度
def apply_discount(price, discount):
    updated_price = price * (1 - discount)
    assert 0 <= updated_price <= price, '折扣价应在 0 和原价之间'
    return updated_price

可以看到,在计算新价格的后面,添加了一个 assert 语句,用来检查折后价格,这里要求新折扣价格必须大于等于 0、小于等于原来的价格,否则就抛出异常。

我们可以试着输入几组数,来验证一下这个功能:

print(apply_discount(100,0.2))
print(apply_discount(100,1.1))

运行结果为:

80.0
Traceback (most recent call last):
  File "C:\Users\mengma\Desktop\demo.py", line 7, in <module>
    print(apply_discount(100,1.1))
  File "C:\Users\mengma\Desktop\demo.py", line 4, in apply_discount
    assert 0 <= updated_price <= price, '折扣价应在 0 和原价之间'
AssertionError: 折扣价应在 0 和原价之间

可以看到,当 discount 是 0.2 时,输出 80 没有问题,但是当 discount 为 1.1 时,程序便抛出下面 AssertionError 异常。

这样一来,如果开发人员修改相关的代码,或者是加入新的功能,导致 discount 数值异常时,只要运行程序就很容易能发现问题,这也从侧面印证了前面多讲的,assert 的加入可以有效预防程序漏洞,提高程序的健壮性。

另外,在实际工作中,assert 还有一些很常见的用法,例如:

def func(input):
    assert isinstance(input, list), '输入内容必须是列表'
    # 下面的操作都是基于前提:input 必须是 list
    if len(input) == 1:
        ...
    elif len(input) == 2:
        ...
    else:
        ...

上面代码中,func() 函数中的所有操作都基于输入必须是列表这个前提。所以很有必要在开头加一句 assert 的检查,防止程序出错。

以上给大家介绍了 2 个有关 assert 的使用场景,很多读者可能觉得,assert 的作用和 if 语句非常接近,那么他们之间是否可以相互替代呢?

要注意,前面讲过,assert 的检查是可以被关闭的,比如在命令行模式下运行 Python 程序时,加入 -O 选项就可以使程序中的 assert 失效。一旦 assert 失效,其包含的语句也就不会被执行。

还是拿 C 语言中文网用户来说,只有 VIP 用户才可以阅读 VIP 文章,我们可以设计如下这个函数来模式判断用户身份的功能:

def login_user_identity(user_id):
    #凭借用户 id 判断该用户是否为 VIP 用户
    assert user_is_Vip(user_id) "用户必须是VIP用户,才能阅读VIP文章"
    read()

此代码从代码功能角度上看,并没有问题,但在实际场景中,基本上没人会这么写,因为一旦 assert 失效,则就造成任何用户都可以阅读 VIP 文章,这显然是不合理的。

所以正确的做法是,使用 if 条件语句替代 assert 语句进行相关的检查,并合理抛出异常:

def login_user_identity(user_id):
    #凭借用户 id 判断该用户是否为 VIP 用户
    if not user_is_Vip(user_id):
        raise Exception("用户必须是VIP用户,才能阅读VIP文章")
    read()

总之,不能滥用 assert,很多情况下,程序中出现的不同情况都是意料之中的,需要用不同的方案去处理,有时用条件语句进行判断更为合适,而对于程序中可能出现的一些异常,要记得用 try except 语句处理(后续章节会做详细介绍)。