乔克视界 乔克视界
首页
  • 运维
  • 开发
  • 监控
  • 安全
  • 随笔
  • Docker
  • Golang
  • Python
  • AIOps
  • DevOps
  • 心情杂货
  • 读书笔记
  • 面试
  • 实用技巧
  • 博客搭建
友链
关于
收藏
  • 分类
  • 标签
  • 归档

乔克

云原生爱好者
首页
  • 运维
  • 开发
  • 监控
  • 安全
  • 随笔
  • Docker
  • Golang
  • Python
  • AIOps
  • DevOps
  • 心情杂货
  • 读书笔记
  • 面试
  • 实用技巧
  • 博客搭建
友链
关于
收藏
  • 分类
  • 标签
  • 归档
  • Docker

  • Golang

  • AIOps

  • Python

    • 基础知识

      • Python之链表
      • Python 之类的初识
      • Python之函数式编程
      • Python之匿名函数
      • Python之自定义函数
      • Python之异常处理
      • Python之条件与循环
      • Python之列表生成式
      • Python之生成器
      • Python之装饰器
      • Python之迭代器
      • Python之进程、线程、协程
      • Python之深浅拷贝
      • Python之反射
      • Python之并发编程
      • Python之垃圾回收机制
      • Python之断言assert
        • assert 基本语法
        • assert 基本用法
        • assert 错误示例
        • 总结
      • Python之上下文管理器和with语句
      • Python中JSON的对应关系
      • Python之单例模式
    • Django框架

    • 其他

  • DevOps

  • 专栏
  • Python
  • 基础知识
乔克
2025-07-19
目录

Python之断言assert

# assert 基本语法

Python 中的 assert 语句是 debug 的好工具,主要用于测试一些条件是否满足。如果测试条件满足,则什么都不做,相当于 pass 语句。如果测试条件不满足,便会抛出异常 AssertionError,并返回具体的错误信息。

它的语法如下:

assert_stmt ::=  "assert" expression ["," expression]
1

先来看一下简单的测试:

>>> assert 1 == 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError
>>> assert 1 == 1
1
2
3
4
5

从上面可以看到,如果测试条件不满足,则抛出异常,如果满足,则什么都不做。

再来看一个指定错误名的测试:

>>> assert 1 == 2, "assert is wrong"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError: assert is wrong
1
2
3
4

从上面可以看到,条件不满足,依然会抛出一样,并且将我们自定义的 异常内容也一并显示出来了。这样就很方便我们调试自己的代码。

注意:不要在使用 assert 的时候加括号,如下:

>>> assert(1 == 2, "assert is wrong")
<stdin>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
>>>
1
2
3

如果按照上面这样写,无论表达式是对还是错,assert 永远不会检查 fail,程序只给你提示 SyntaxWarning。正确的写法应该是不带括号的。

总的来说,assert 在程序中的作用,是对代码进行 safe-check,使用 assert,就表示你很确定这个条件一定会发生或者一定不会发生。举个例子,如果你有一个函数,其中一个参数是人的性别,正常情况下,性别只有男女之分,这时候就可以使用 assert 来防止非法输入,如果你的程序没有 bug,那么 assert 就永远不会执行,如果一旦抛出异常,你也能很方便的知道程序出现了问题,并且很清楚问题出现在什么地方。

# assert 基本用法

通过应用场景来简述 assert 的基本用法。

第一个场景:假设现在有一个促销活动,要对一些商品进行打折,这时候就可以写一个函数,要求输入原来的价格和折扣,输出打折后的价格。

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
1
2
3
4

可以看到在计算价格的后面加入了一个 assert 语句,折后价格应该大于 0 并且小于现有价格,如果不在这个区间内就抛出异常。

测试如下:

apply_discount(100, 0.2)
80.0

apply_discount(100, 2)
AssertionError: price should be greater or equal to 0 and less or equal to original price

1
2
3
4
5
6

可以看到,在正常价格内就不会抛出异常,否则就会抛出异常。这样对于开发人员来说就会很容易的发现问题,并且知道问题的位置。

第二个场景:最常见的除法操作,假设后台想知道每个商品的平均价格和售卖数量还有销售总额,这样可以写成如下函数:

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
1
2
3

同样,我们插入了 assert,表明销售数目必须大于 0。

除了上面这两个场景,assert 还有一些很常见的用法,如下:

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

这个 func 函数的所有操作,都必须基于 input 是 list 的前提。

# assert 错误示例

上面说了 assert 的几种常见的使用场景,可能给人一个错觉,我们在很多地方都可以使用 assert,那么我们是不是可以将很多 if 语句都换成 assert 呢?我们还是从一个例子来看。

例子:后台要删除一些上线时间较长的商品,于是,开发人员就设计了下面一段代码:

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)
1
2
3
4

按规定,要删除商品,必须是 admin 用户才有权限删除,所以就设计了上面这种代码。按理说上面这种设计也没毛病,但是 assert 语法是可以被关闭的,当我们在运行 python 程序的时候加-o 参数,就会忽略掉 assert 语句,因此,一旦 assert 失效,上面那两个 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)

1
2
3
4
5
6
7

再看一个例子,如果想打开一个文件,进行读取,处理等一系列操作,那么下面的写法显然是有问题的。

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

因为 assert 的使用,表示你强行需要文件必须存在,但事实上很多情况下这种假设并不成立,所以就会抛出异常,正确的做法如下:

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

1
2
3
4
5
6
7

总的来说,assert 并不设置 run-time error 的检查。

# 总结

assert 通常是用来对代码进行 safe-check,表明你确定这种情况一定发生或者一定不发生,需要主义的是使用 assert 一定不要加括号,否则无论表达式对错,assert 都不会检查 failed,另外,程序中的 assert 语句可以通过-o 等选择被全局 disabled。

合理使用 assert,可以提升代码的健壮性,同时也方便排查问题。

但是,assert 不可以进行滥用,很多情况下,程序中出现的不同情况都是意料之中的,需要我们用不同的方案去处理,这时候用条件语句进行判断更合适,对于程序中的一些 run-time error,用异常处理。

作者:乔克

本文链接:https://jokerbai.com

版权声明:本博客所有文章除特别声明外,均采用 署名-非商业性-相同方式共享 4.0 国际 (CC-BY-NC-SA-4.0) 许可协议。转载请注明出处!

上次更新: 2025/07/19, 11:33:23
Python之垃圾回收机制
Python之上下文管理器和with语句

← Python之垃圾回收机制 Python之上下文管理器和with语句→

最近更新
01
使用 Generic Webhook Trigger 触发 Jenkins 多分支流水线自动化构建
07-19
02
使用Zadig从0到1实现持续交付平台
07-19
03
基于Jira的运维发布平台
07-19
更多文章>
Theme by Vdoing | Copyright © 2019-2025 乔克 | MIT License | 渝ICP备20002153号 |
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式