Python 进阶教程:断言语法

1.  什么是断言?

断言,简而言之,就是检查代码中的某个条件是否为真。如果条件为真,程序继续执行;如果条件为假,程序会引发一个AssertionError异常。在Python中,我们可以使用assert关键字来进行断言。

2.  断言的语法和用法

2.1  断言的语法格式

assert 表达式 ,"错误信息"

其中,表达式是你想要检查的条件,而"错误信息"是当条件为假时你想要显示的错误信息。这个错误信息是可选的,但通常很有用,因为它可以帮助你理解为什么断言失败了。

类比 if 语句,如下所示:

if not 表达式:
	raise AssertionError

assert 表达式之后,可以增加一个参数 [, arguments],等价的 if 语句如下所示:

if not 表达式:
	raise AssertionError(arguments)

2.2 断言的用法

2.2.1  基本用法
assert 5 > 3   # 这会成功,因为5确实大于3
# 带有错误信息的用法

assert 3 > 5, "3怎么可能大于5呢?" 

# 这会引发一个AssertionError,并显示错误信息“3怎么可能大于5呢?”
2.2.2 有效用法

如:在游戏里面设置一个未满 18 岁禁止访问的功能。

def overage18(age):
    assert age >= 18, "对不起未满18岁,无法进行游戏"
    print("享受欢乐游戏时光")

if __name__ == '__main__':
    overage18(15)

但是这个案例并不是一个完美的案例,因为断言是为了告知开发人员 ,你写的程序发生异常了。

断言主要为调试辅助而生,为的是程序自检,并不是为了处理错误,程序 BUG 还是要依赖 try… except 解决。

由于断言是给开发人员看的,所以下述案例的断言是有效的。

def something():
	"""该函数执行了很多操作"""
	my_list = [] # 声明了一个空列表
	# do something
	return my_list

def func():
	"""调用 something 函数,基于结果实现某些逻辑"""
	ret = something()
	assert len(ret) == 18, "列表元素数量不对"
	# 完成某些操作

使用断言要注意:
不要用断言验证用户的输入,这是因为 python 通过命令行运行时,如果增加 -O 标识,断言就被全局禁止了,你的所有验证就都丢失了。

3.  断言的常用函数

  • assertEqual(a,b,msg=msg):判断两个值是否相等;
  • assertNotEqual(a,b,msg=msg):上一函数的反义;
  • self.assertTrue(a,msg=none):判断变量是否为 True;
  • assertFalse(a,msg=none):同上反义;
  • assertIsNone(obj=‘’):判断 obj 是否为空;
  • assertIsNotNone(obj=‘’):同上反义;
  • 4.  断言的常见错误与陷阱

    4.1  忘记写条件

    如果你忘记了写条件,Python会引发一个SyntaxError。例如:assert, "没有条件"

    4.2  错误的处理方式

    尽管你可以使用assert来检查任何条件,但并不适用于所有情况。对于可能会引发错误的操作,最好使用try/except结构来处理异常。例如:

    try:
        x = 1 / 0  # 这将引发一个ZeroDivisionError异常
    except ZeroDivisionError:
        print("除数不能为0!")  # 处理异常并打印错误信息

    4.3  断言在生产环境中的使用

    在生产环境中,你可能不希望由于断言失败而中断程序。为了解决这个问题,你可以使用-O(大写的字母O)命令行选项来关闭断言检查。例如:python -O your_script.py。但是,请注意,这可能会导致你的程序在某些情况下表现出意外的行为。

    4.4  陷阱:断言与条件语句

    尽管断言和条件语句看起来很像,但它们的目的不同。条件语句用于控制程序流程,而断言用于验证代码中的某些假设是否成立。因此,不要混淆它们。

    例如:使用if语句和assert语句的比较。

    # 使用if语句检查年龄是否合法(这里假设年龄合法范围是18-60) 
    if age < 18 or age > 60: 
        print("年龄不在合法范围内!") 
    
    # 如果年龄不在合法范围内,输出错误信息并结束程序运行 
    
    # 使用assert语句进行同样的检查 
    assert 18 <= age <= 60, "年龄不在合法范围内!" 
    
    # 如果年龄不在合法范围内,引发AssertionError异常

    5.  实际应用场景

    5.1  参数检查

    在函数或方法中,你可以使用断言来检查传递的参数是否满足某些条件。例如:在计算面积的函数中,可以检查传入的参数是否为正数。如果参数小于或等于0,则使用断言抛出错误。例如:面积函数参数检查。

    def calculate_area(radius): 
    
        # 检查半径是否大于0,如果不满足条件,则抛出错误信息并结束程序运行 
        assert radius > 0, "半径必须大于0!" 
        # 计算圆的面积并返回结果(这里假设π取3.14)
        return 3.14 * radius * radius 

    5.2  边界条件检查

    对于一些算法或数据结构,你可能知道它们应该在特定的条件下工作得最好。使用断言可以帮助你确保这些条件被满足。

    边界条件检查是编程中一个重要的环节,用于确保程序在处理数据时不会超出预期的范围。assert语句是Python中用于进行边界条件检查的一种方式。当assert后面的条件为False时,程序会引发一个AssertionError异常。

    def square(n):  
        assert n >= 0, "输入必须为非负数"  
        return n ** 2

    在上述示例中,函数square接受一个参数n,并返回其平方。在函数内部,使用assert语句来检查输入参数n是否为非负数。如果n小于0,则assert后面的条件为False,程序将引发一个带有错误信息的AssertionError异常。

    通过这种方式,我们可以确保在计算平方之前输入参数满足一定的条件,从而避免因输入不合法而导致程序出错。

    5.3  调试和测试

    assert语句是一种方便的调试和测试工具,用于在代码中插入检查点并验证程序的特定条件是否满足预期。它可以帮助程序员发现和修复错误,提高代码的健壮性和可靠性。

    def calculate_average(numbers):  
        total = sum(numbers)  
        average = total / len(numbers)  
        assert len(numbers) > 0, "列表不能为空"  
        assert average >= 0, "平均值不能为负数"  
        return average

     在上述示例中,函数calculate_average计算给定数字列表的平均值。在计算平均值之前,使用两个assert语句进行条件检查。第一个assert检查列表是否为空,如果为空则引发一个带有错误信息的AssertionError异常。第二个assert检查计算出的平均值是否大于等于0,如果小于0则同样引发异常。

    通过在代码中插入assert语句,可以确保在计算平均值之前列表不为空且平均值符合预期。如果这些条件不满足,程序将引发异常并输出错误信息,从而帮助程序员快速定位和修复问题。

    5.4  程序完整性检查

    使用assert进行程序完整性检查是一种常见的做法,它可以帮助确保程序的某些关键条件在执行过程中始终为真。如果这些条件不满足,assert语句将引发一个异常,从而提醒程序员存在潜在的问题。

    以下是一个使用assert进行程序完整性检查的示例:

    def validate_data(data): 
        assert isinstance(data, dict), "输入必须是一个字典" 
        assert 'name' in data, "字典中必须包含'name'键" 
        assert 'age' in data, "字典中必须包含'age'键" 
        return data

    在上述示例中,函数validate_data接受一个参数data,并使用assert语句进行完整性检查。首先,它检查data是否为一个字典,如果不是则引发异常。然后,它检查字典中是否包含必要的键,如'name'和'age'。如果缺少这些键,同样会引发异常。

    通过使用assert语句进行完整性检查,可以确保输入数据满足程序的要求。如果输入数据不满足条件,程序将通过异常提醒程序员,这有助于及早发现潜在的错误。

    5.5  防止未来的更改破坏代码

    有时候,一些代码的设计决策是基于某些假设的。使用断言可以帮助你确保这些假设在未来不会被破坏。例如:在设计一个API时选择了一个特定的参数顺序,你可以使用断言来确保未来的更改不会破坏这个顺序。例如:API参数顺序检查。

    def process_data(param1, param2): 
        # 检查param1是否为空,如果为空则抛出错误信息并结束程序运行 
        assert param1 is not None, "param1不能为空!" 
    
        # 检查param2是否为空,如果为空则抛出错误信息并结束程序运行 
        assert param2 is not None, "param2不能为空!" 
    
    # 在这里进行数据处理操作...

    5.6  简化复杂的条件语句

    有时候,你可能需要在一个复杂的条件语句中使用多个断言来检查多个条件。这可以使代码更易读,并帮助你更好地理解这些条件之间的关系。

    例如:条件语句简化。

    # 如果a和b都大于0,则继续执行后面的代码
    if assert(a > 0) and assert(b > 0):  
    
    # do something...

    5.7  确保代码的正确执行顺序

    例如在编写一个多线程程序时,需要确保线程的执行顺序是正确的。可以使用断言来验证线程的执行顺序。

    class MyThread(threading.Thread): 
        def __init__(self): 
        threading.Thread.__init__(self) 
        self.start_time = None 
    
    
    def run(self): 
        self.start_time = time.time() 
        # 执行一些操作... 
        assert self.start_time is not None, "线程启动时间未设置!"

    assert self.start_time is not None, "线程启动时间未设置!":这行代码使用 Python 的断言语句来检查 start_time 是否被正确设置(即不为 None)。如果 start_timeNone,则抛出一个带有错误消息的异常。这个断言用于确保线程已经成功启动并设置了启动时间。

    这段代码定义了一个自定义线程类,该类继承自 Python 的内置线程类,并在其运行开始时自动设置一个时间戳。这是通过重写 run 方法并设置一个断言来实现的,以确保线程在执行任何其他操作之前已经成功启动。

    在上面的例子中,如果在run方法中尝试访问start_time属性,而该属性尚未被设置,断言将会失败,并引发一个AssertionError异常。这有助于确保线程的执行顺序是正确的。

    作者:我自纵横2023

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python 进阶教程:断言语法

    发表回复