开放的编程资料库

当前位置:我爱分享网 > Python教程 > 正文

Python 断言

Python断言教程展示了如何在Python中使用断言。我们定义断言,解释断言和异常之间的区别,并展示它们与单元测试的关系。

断言

断言是代码中的内部自检;它们适合开发人员尽快发现错误。断言的目的是在程序的早期检测问题,原因很清楚,并避免它们作为其他操作的副作用弹出。

断言不应该用于数据处理或验证,因为它们在生产中被关闭。一些编程语言,例如Go,不使用断言。其他语言也有assert语句,但很少使用(Java)。

断言与异常

断言是布尔表达式,必须为真才能使代码正确。断言失败会导致代码更正。异常是关于可能在运行时发生的非典型情况的指示。异常可能不会导致代码中缀。例如,如果Internet连接中断,或文件权限不足,则用户必须进行处理。断言不应用于处理运行时错误。

按合同设计

按合同设计或按合同编程是一种软件开发实践,开发人员在其中为软件组件定义正式、精确和可验证的接口规范。规范分为前置条件、后置条件和不变量。

先决条件是在执行一段代码之前必须始终为真的谓词。poscondition是一个谓词,在执行一段代码后必须始终为真。不变量是在所有操作之后保持不变的属性。

合同设计方法是在1980年代发展起来的,受到商业合同的启发。

断言和单元测试

断言和单元测试在某些方面有重叠,但也存在一些差异。断言是对程序内部状态的假设,而单元测试检查模块的外部行为。单元测试使用测试数据,而断言则不行。

断言语句用于单元测试。经典断言是关于真实情况的假设,而在单元测试中,开发人员经常测试错误条件。

Python断言

assert语句是将调试断言插入Python程序的便捷方式。使用-O-OO选项和PYTHONOPTIMIZE变量删除断言语句。

Pythonassert语句由一个布尔条件和一个可选的错误消息组成,以逗号分隔。

Python断言示例

以下示例展示了Pythonassert语句的用法。

#!/usr/bin/python

def info(age, name):

    assert age >= 18 and age <= 65, 'age value must be between values 18 and 65'

    print(f'{name} is {age} years old')


age = 84
name = 'Peter'

info(age, name)

在这个例子中,我们有一个关于年龄值的先决条件。

$ ./precondition.py
Traceback (most recent call last):
  File "./precondition.py", line 14, in <module>
    info(age, name)
  File "./precondition.py", line 6, in info
    assert age >= 18 and age <= 65, 'age value must be between values 18 and 65'
AssertionError: age value must be between values 18 and 65

程序失败,因为前提条件无效。

#!/usr/bin/python

def do_discount(price, discount):

    discounted_price = price - discount * price
    assert 0 < discounted_price < price, 'discounted price must be greater than zero and lower than original price'

    return discounted_price

price = 120
discount = 0.2

dis_price = do_discount(price, discount)
print(dis_price)

第二个例子有一个关于折扣价的后置条件。它必须大于零且低于原始价格。

单元测试中的Python断言

Python有几个流行的单元测试框架,包括pytestunittestnose。虽然pytestnose使用assert语句,但unittest支持assertEqual等函数和assertLess

Pytest示例

下面的例子展示了pytest框架的使用。

def max(values):

  _max = values[0]

  for val in values:
      if val > _max:
          _max = val

  return _max


def min(values):

  _min = values[0]

  for val in values:
      if val < _min:
          _min = val

  return _min

我们在一个模块中有两个算法。

#!/usr/bin/python

import algo

def test_min():
    values = (2, 3, 1, 4, 6)

    val = algo.min(values)
    assert val == 1

def test_max():
    values = (2, 3, 1, 4, 6)

    val = algo.max(values)
    assert val == 6

我们将测试数据传递给被测试的algo函数。我们使用assert语句检查预期值。

$ pytest-3 min_max_test.py
============================================================= test session starts =============================================================
platform linux -- Python 3.7.6, pytest-4.6.9, py-1.8.1, pluggy-0.13.0
rootdir: /root/Documents/prog/python/assert
collected 2 items

min_max_test.py ..

我们运行测试。

单元测试示例

现在我们用unittest测试同一个模块。

#!/usr/bin/python

import unittest
import algo


class SimpleTest(unittest.TestCase):

    def test_min(self):
        values = (2, 3, 1, 4, 6)

        val = algo.min(values)
        self.assertEqual(val, 1)

    def test_max(self):
        values = (2, 3, 1, 4, 6)

        val = algo.max(values)
        self.assertEqual(val, 6)

if __name__ == '__main__':
    unittest.main()

在示例中,我们使用了assertEqual断言。

$ ./min_max_test.py
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

我们运行测试。

在本教程中,我们使用了Pythonassert语句并大体解释了断言。

列出所有Python教程。

未经允许不得转载:我爱分享网 » Python 断言

感觉很棒!可以赞赏支持我哟~

赞(0) 打赏