Python 异常处理:Python 中的断言

概述

在Python编程中,我们有一个特殊的关键字,称为Assert。它只是接受一个布尔条件的输入,当返回 true 时不会返回任何内容。不过,如果计算结果为 false,则会引发 AssertionError 以及可选消息。

Python 断言简介

在编程过程中,程序员多次知道某些条件或假设总是为真。如果在程序执行期间的任何时间点,任何条件为 True 的语句的计算结果为 False,则不应允许代码进一步执行。本质上,一旦我们发现不应该存在的可疑内容,我们就会立即终止程序。这个任务是在assert的帮助下完成的。

什么是断言?

断言语句可用于验证您在代码中所做的任何逻辑假设。它主要用作调试工具。例如,如果我们编写一个执行除法的函数,我们知道除数不能为零,因此我们“断言”除数不应等于零,以防止可能发生的任何类型的错误/错误由于后面的代码中出现了这个问题。

作为输入,Python 中的断言采用要计算的表达式和[错误消息,这是可选的。基本上,当代码遇到任何断言语句时,可能会发生以下两种情况之一。

一、代码运行没有任何问题;第二,它抛出一个断言错误,终止程序。我们将深入研究这些情况,但我们必须首先了解为什么应该使用断言语句。

为什么在 Python 中使用断言?

Python 中的断言语句可以立即识别程序中的问题,原因很明确,而不是等到其他操作失败时才识别。

它们可以称为代码的内部自检查。使用断言语句的目的是让开发人员能够快速跟踪代码中错误的根本原因。

在测试或保证任何应用程序或软件的质量时,断言语句特别有用。

Python 断言语句

句法:

 
assert  , 

如上所述,我们有一个条件和一条错误消息作为断言语句的一部分。如果断言语句中使用的条件计算结果为 True,则代码正常运行,即不会引发错误或终止程序。另一方面,如果它的计算结果为 False(不需要的条件),它会抛出一个 AssertionError 以及错误消息(如果提供)并终止程序。

在Python中断言,

 
assert 

几乎与此类似:

 
if __debug__:
    if not :
        raise AssertionError()

这里的__debug__是什么 ?它是一个常量,Python 使用它来确定是否必须执行像assert 这样的语句。

在Python编程语言中,无论我们使用assert语句,还是使用if引发错误,它们没有任何重大区别,它们几乎相似。当调试模式打开时(__debug__ == True ),带有if 的代码会引发 AssertionError ,并且提供的条件计算结果为 False。

当我们可以使用if语句时(这肯定更容易理解),为什么还要使用 assert 语句呢?有两个主要原因 - 可读的代码,以及在需要时禁用断言语句的选项。

使用断言语句代替if条件使代码更具可读性且更短。与if条件相比,使用断言语句的优点是可以禁用断言语句,这与 IF 条件不同。

要禁用程序中的任何断言语句,请在优化模式下运行 Python ( __debug__ == False ),忽略所有断言语句。可以通过-O标志来实现相同的目的。

python -O 程序.py

现在我们已经了解了断言语句的语法以及它相对于if 的优势,让我们继续看看它在 Python shell 中的样子以及如何运行它:

 
>>> assert True # nothing, because  is True>>> assert False # will raise an error but no message, since not specifiedTraceback (most recent call last):
  File "", line 1, in AssertionError
>>> assert False, "This statement is False" # condition is False, hence error + message, since it is specifiedTraceback (most recent call last):
  File "", line 1, in AssertionError: This statement is False

如果断言失败,可以像上面的 shell 示例中那样打印一条消息:

 
assert False "This assertion has failed"

不添加错误消息不会对程序的运行方式产生任何影响。显示的错误将是如上例所示的回溯错误,并终止程序。它只是有助于更清楚地理解断言错误。

Python 中的断言错误会终止您编写的程序,但是,如果我们不希望这种情况发生怎么办?如果我们希望代码按原样运行,并且同时希望检测到错误,该怎么办?

这个问题的解决方案是try- except块。 Python 中的 try-except 块是 Python 中处理和检查错误的另一种方法。首先,当程序中没有任何错误并且跳过 except 子句时,只有在 try 块内编写的代码才会被执行。当 try 块中出现错误时,将执行 except 块中的代码,并跳过 try 块中的代码。

以下是我们如何使用 try-except 块处理基本的除以 0 断言错误:

 
try:
  x = 1
  y = 0
  assert y != 0 , "Division by zero not possible!"
  print(x / y)
except for AssertionError as msg:
  print(msg) # error message given by user gets printedprint("The rest of the program still runs!")

让我们尝试理解上面的代码中发生了什么。我们使用了一个断言语句,正如我们上面所读到的,在条件评估为 False 时打印一条错误消息,并且我们还在except 块中打印一条消息。我们在这里做什么,为什么?

当我们在 try 块中时,x 的值为 1,y 的值为 0,并且断言条件可防止任何数字除以 0。现在,由于 y 的值为 0,我们的断言语句的计算结果为 False因此抛出一个断言错误。我们知道这些错误会终止程序,但由于我们不希望它终止,所以我们使用 try-except。一旦 try 块中出现错误,我们立即转移到 except 块来处理错误。

当我们编写带有条件和错误消息的简单断言语句时,会打印什么?错误消息。所以, except 块

 
>>> assert(2 + 3 == 6, "Incorrect addition") # wrong>>> assert 2 + 3 == 6, "Incorrect addition" # correct

第一个带括号的语句将不起作用,因为您实质上是为断言语句提供了一个元组。 Python 中元组的格式为 (Val1, Val2, …),任何在 bool 上下文中编写的元组始终为 true,除非它不包含任何值。这意味着如果我们不为断言语句提供任何条件,例如:

断言()

它会引发一个 AssertionError 因为空元组是 False。

断言错误对我们的代码有什么影响?

在多次阅读和理解未处理的断言终止程序后,我想到了一个问题——它将如何终止程序?

本质上有两种停止程序执行的方法——通过exit()和通过abort()。

当使用 exit() 终止程序时,该函数执行刷新未写入的缓冲数据、关闭打开的文件以及删除临时文件,并向操作系统返回整数退出状态。

abort ()函数可能不会关闭任何打开的文件,可能不会刷新流缓冲区,也可能不会删除任何临时文件。两种终止程序的函数之间的一个主要区别是abort()导致异常终止,而exit()导致正常终止。

当断言语句中提到的条件返回 False 时,在abort()函数的帮助下,程序会因断言语句而终止。

最后,既然我们知道断言是什么、为什么它有用以及如何解决它,我们必须解决房间里的大象问题。具体可以用在哪里呢?

我们在 Python 中什么地方使用断言?

断言不用于标记预期的错误情况,类似于“找不到文件”,用户可以在其中进行恢复性移动(或只是再次尝试)。相反,assert 语句主要用于调试目的,

1. 检查参数类型/类/值

如果您的程序倾向于控制用户输入的每个参数或其他任何参数,则可以使用断言语句

例子:

 
def kelvin_to_fahrenheit(Temp):
   assert (Temp >= 0),"Colder than absolute zero!" # User input cannot violate a fact, hence the use of assert return ((Temp - 273) * 1.8) + 32

2. 检查“不可能发生”的情况

虽然断言语句在调试程序时很有用,但在用于检查用户输入时不鼓励使用,除非它破坏了普遍真理。该陈述只能用于识别任何“这不应该发生”的情况,即任何事实或绝对正确的陈述由于代码中的错误而变为假的情况。

例如,如果用户输入的字符少于输入中所需的字符,则不能将其称为“这不应该发生”的情况,其中必须使用断言语句,因为用户没有违反任何事实意味着永远是真的。对于诸如此类的琐碎问题使用断言语句并不是一个错误,但它被认为是一种不好的做法。

 
def something(s: str): # a function that takes a long string as the input to do something assert len(s) >= 8 # bad practice, the length of the input string doesn't violate a universal truth # do something

然而,如果一个程序涉及圆的半径和直径的计算,并且圆的半径在程序中的任何点都不是直径的一半,那么这属于“这不应该发生”的情况,如下所示这是无法改变或违反的事实。

例如,

 
# some complex operations involving the radius of a circle assert radius == diameter / 2, "Calculations have corrupted the value of radius!!!"
# return statements with radius or continuation in the program

如果在复杂的操作过程中,半径的值发生变化并且不等于直径的一半,我们的断言语句条件会立即检测到它并抛出错误,以避免代码中出现任何进一步的复杂性/错误或提供不需要的输出。

3. 理解文件

在代码中使用断言语句对于记录程序员对代码的理解很有用。它使程序员自己以及将来处理相同代码的任何其他人都清楚自己的假设。如果出于任何原因,将来代码被破坏,失败的原因将是显而易见的,并且下次断言条件评估为 False 时,调用者将得到 AssertionError 异常。

Python 中断言的另一个例子

假设您有一个函数可以计算折扣后商品的成本。在这种情况下,我们可以肯定地说,折扣后的成本肯定会大于0且小于原始成本。

如果折扣成本不在这个范围内,那么我们就处于“这不应该发生”的情况。因此,我们使用assert语句。

 
def calculate_discount(cost, discount):
    discounted_cost = cost - [discount * cost]
    assert 0 <= discounted_cost <= cost # used an assert because a fact could have been violated, and also serves as a depiction of the understanding of the programmer return discounted_cost

结论

  • Python 中的断言或断言可帮助您在程序中自信地陈述事实,它有助于验证任何代码中的逻辑假设
  • Python中assert语句的语法:
     
    assert  , 
    • 代码中的错误消息是可选的,但编写的目的是为了清楚地理解引发错误的原因
    • 未处理的断言错误使用abort()终止程序,但如果我们不想终止程序,可以使用try- except块来处理它们
    • 如果断言语句中使用的条件== False ,则会抛出AssertionError(),但当条件计算结果为 True 时,代码运行顺利
    • Python 中的断言语句可用于:
      • 调试目的
      • 检查“不可能发生”的情况
      • 理解的文件
      • 内部不变量
    • Python Assert 语句不得与括号一起使用,也不能用于基本的用户输入验证。它们必须用于“这不应该发生”的情况。