Is there a performance or code maintenance issue with using assert as part of the standard code instead of using it just for debugging purposes? Is assert x >= 0, 'x is less than zero' better or worse than if x < 0: raise Exception('x is less than zero') Also, is there any way to set a business rule like if x < 0 raise error that is always checked without the try/except/finally so, if at anytime throughout the code x is less than 0 an error is raised, like if you set assert x < 0 at the start of a function, anywhere within the function where x becomes less then 0 an exception is raised?
当前回答
除了其他答案之外,断言本身也会抛出异常,但仅抛出AssertionErrors。从实用主义的角度来看,当您需要对捕获的异常进行精细控制时,断言并不适合。
其他回答
除了其他答案之外,断言本身也会抛出异常,但仅抛出AssertionErrors。从实用主义的角度来看,当您需要对捕获的异常进行精细控制时,断言并不适合。
这是一个悬而未决的问题,我有两个方面想涉及:何时添加断言以及如何编写错误消息。
目的
向初学者解释一下,断言是一种可能引发错误的语句,但您不会捕获它们。他们通常不应该被抚养,但在现实生活中,他们有时还是会被抚养。这是一个严重的情况,代码无法恢复,我们称之为“致命错误”。
其次,它是为了“调试目的”,虽然正确,但听起来非常轻蔑。我更喜欢“声明不变量,它永远不应该被违反”的提法,尽管它对不同的初学者有不同的作用……有些人“只是得到它”,而另一些人要么没有找到它的任何用途,要么取代正常的异常,甚至用它来控制流。
风格
在Python中,assert是语句,而不是函数!(记住assert(False, 'is true')不会引发。但是,先说一下:
何时以及如何编写可选的“错误消息”?
这实际上适用于单元测试框架,它通常有许多专用的方法来执行断言(assertTrue(条件),assertFalse(条件),assertEqual(实际的,预期的)等)。它们通常还提供了一种对断言进行评论的方法。
在一次性代码中,您可以不使用错误消息。
在某些情况下,没有什么可以添加到断言:
def垃圾场(东西): 屁 # ...
但除此之外,消息对于与其他程序员(有时是你代码的交互式用户,例如在Ipython/Jupyter等)的交流是有用的。
给他们信息,而不仅仅是泄露内部实现细节。
而不是:
assert meaningless_identifier <= MAGIC_NUMBER_XXX, 'meaningless_identifier is greater than MAGIC_NUMBER_XXX!!!'
写:
assert meaningless_identifier > MAGIC_NUMBER_XXX, 'reactor temperature above critical threshold'
或者甚至:
assert meaningless_identifier > MAGIC_NUMBER_XXX, f'reactor temperature({meaningless_identifier }) above critical threshold ({MAGIC_NUMBER_XXX})'
我知道,我知道——这不是静态断言的情况,但我想指出消息的信息值。
消极还是积极的信息?
这可能是有争议的,但读到这样的东西让我很受伤:
assert a == b, 'a is not equal to b'
这是两个相互矛盾的东西。因此,每当我对代码库产生影响时,我就会通过使用“必须”和“应该”等额外的动词来明确我们想要什么,而不是说我们不想要什么。 断言a == b, 'a必须等于b'
然后,获取AssertionError: a must equal to b也是可读的,并且语句在代码中看起来是合乎逻辑的。此外,您可以在不读取回溯(有时甚至不可用)的情况下从中获得一些信息。
"assert"语句在编译优化时被删除。所以,是的,它们在性能和功能上都有差异。
在编译时请求优化时,当前代码生成器不会为assert语句生成代码。Python 3 Docs
如果您使用assert来实现应用程序功能,然后优化部署到生产环境,那么您将受到“但它在开发中有效”缺陷的困扰。
参见PYTHONOPTIMIZE和-O -OO
assert的使用和异常的引发都与通信有关。
Assertions are statements about the correctness of code addressed at developers: An assertion in the code informs readers of the code about conditions that have to be fulfilled for the code being correct. An assertion that fails at run-time informs developers that there is a defect in the code that needs fixing. Exceptions are indications about non-typical situations that can occur at run-time but can not be resolved by the code at hand, addressed at the calling code to be handled there. The occurence of an exception does not indicate that there is a bug in the code.
最佳实践
因此,如果您将运行时发生的特定情况视为您想要通知开发人员的错误(“嗨,开发人员,这种情况表明某处存在错误,请修复代码。”),那么请使用断言。如果断言检查代码的输入参数,当输入参数违反条件时,您通常应该在文档中添加代码具有“未定义行为”。
相反,如果这种情况的出现并不是您眼中的错误,而是您认为应该由客户端代码处理的(可能很少,但可能)情况,则引发异常。引发哪种异常的情况应该是相应代码文档的一部分。
有没有演出[…]使用assert时的问题
断言的计算需要一些时间。但是,它们可以在编译时被删除。然而,这有一些后果,见下文。
有[…]使用assert的代码维护问题
Normally assertions improve the maintainability of the code, since they improve readability by making assumptions explicit and during run-time regularly verifying these assumptions. This will also help catching regressions. There is one issue, however, that needs to be kept in mind: Expressions used in assertions should have no side-effects. As mentioned above, assertions can be eliminated at compile time - which means that also the potential side-effects would disappear. This can - unintendedly - change the behaviour of the code.
在诸如PTVS、PyCharm、Wing assert isinstance()等IDE中,可以使用isinstance语句对一些不清楚的对象启用代码补全。
推荐文章
- python:将脚本工作目录更改为脚本自己的目录
- 如何以编程方式获取python.exe位置?
- 如何跳过循环中的迭代?
- 使用Pandas为字符串列中的每个值添加字符串前缀
- ImportError:没有名为matplotlib.pyplot的模块
- 在python中遍历对象属性
- 如何在Python中使用方法重载?
- 在Python中提取文件路径(目录)的一部分
- 如何安装没有根访问权限的python模块?
- 尝试模拟datetime.date.today(),但不工作
- 将行添加到数组
- 如何在Python中直接获得字典键作为变量(而不是通过从值搜索)?
- Python:为什么functools。部分有必要吗?
- 如何用python timeit对代码段进行性能测试?
- Python迭代器中的has_next ?