Python中assert的用法示例是什么?

11

我已经阅读了关于何时使用assert和异常的相关内容,但仍然无法理解。似乎每当我认为应该使用assert时,在开发的后期,我会发现自己在“先验判断”以确保在调用函数时断言不会失败。由于还有一种Python惯用语句是优先使用try-except,因此我通常放弃使用assert并抛出异常。迄今为止,我还没有找到适合使用assert的地方。是否有人能提供一些好的例子呢?

4个回答

23
一个好的指导原则是在你的代码中触发 bug 时使用 assert。当你的代码假定某些东西并基于这个假设采取行动时,建议使用assert 来保护这个假设。这个 assert 失败意味着你的假设不正确,这也意味着你的代码不正确。

16

通常情况下,人们会使用assert去检查那些永远不应该发生的事情,有点像做一次健康检查。

另一个需要注意的事情是,当代码被优化时,assert语句会被移除:

当前的代码生成器在编译时请求进行优化时,不会为assert语句生成任何代码。


4
感谢您指出如果使用-O标志调用Python,则会删除assert(断言)。关键是,如果您期望在去除assert之后代码的行为有所不同,那么您正在误用它们 - 它们仅用于调试。 - Scott Griffiths

3
一个很好的例子是检查函数参数的一致性:
def f(probability_vector, positive_number):
    assert sum(probability_vector) == 1., "probability vectors have to sum to 1"
    assert positive_number >= 0., "positive_number should be positive"
    # body of function goes here

1
有趣的是,我不知道 0.0.0 的速记方式。但是 repl 显示它确实是这样的。虽然在真正的代码中我可能不会使用它,因为它似乎过于“聪明”而容易被忽略。它可能会被误解为打字错误,但 0.0 总是被理解为浮点数。 - Daenyth
这似乎类似于我有一个从2D矩阵中获取元素的函数的情况。 断言行和列输入实际上在矩阵的边界内是有意义的。 但后来我做了一些事情,我想拿一个元素并想对相邻的元素进行操作。 一旦我开始编写代码,当元素位于边缘时,我必须有特殊情况,因为相邻的元素在矩阵外面。 使用异常似乎更好。 - Colin
异常如何使修改代码更容易?当您更改函数的行为时,仍然必须修改引发异常的部分,不是吗? - pberkes
5
这不是使用assert的正确方式。如果代码存在缺陷,断言应该失败,而不是在输入略有不符合预期时失败。如果我从调用别人的函数中得到ValueError(或类似的错误),我知道我传递了无效的参数。但是当我得到AssertionError时,我必须假设函数出现了问题(参见其他回答:断言是检查代码是否正常的方法)。-1 - user395760
这个决定与使代码更易修改无关,而是与使用try块而不是在调用函数之前检查值有关。 - Colin
1
@delnan:一个很好的观点,我想这取决于你想用assert语句实现什么。我经常使用与第一个断言非常接近的东西作为防御性代码,以确保累积的浮点误差不会使概率向量无效。我同意对于库中的公共函数,用户应该以更详细的方式被告知错误。 - pberkes

3

一般来说,assert用于验证您对代码的假设,即在此时点,要么断言成功,要么您的实现存在错误。异常实际上是期望发生错误并“接受”它,即允许您处理它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接