Python的`assert`语句有哪些可接受的使用场景?
我经常使用Python的assert语句来检查用户输入,如果出现问题就快速失败。我知道在使用-o
(优化模式)运行Python时,assert会被去掉。我个人不在优化模式下运行我的应用,但我觉得还是应该避免使用assert,以防万一。
写起来感觉更简洁的是
assert filename.endswith('.jpg')
而不是
if not filename.endswith('.jpg'):
raise RuntimeError
使用assert的这个情况算不算合理呢?如果不算,那么assert语句的合理使用场景是什么呢?
8 个回答
9
完全正确。断言是对你程序状态的一种正式声明。
你应该在一些无法证明的事情上使用它们。不过,它们也很适合用来检查你认为可以证明的逻辑。
再举个例子。
def fastExp( a, b ):
assert isinstance(b,(int,long)), "This algorithm raises to an integer power"
etc.
还有一个例子。最后的那个断言有点傻,因为它应该是可以证明的。
# Not provable, essential.
assert len(someList) > 0, "Can't work with an empty list."
x = someList[]
while len(x) != 0:
startingSize= len(x)
... some processing ...
# Provable. May be Redundant.
assert len(x) < startingSize, "Design Flaw of the worst kind."
再来一个。
def sqrt( x ):
# This may not be provable and is essential.
assert x >= 0, "Can't cope with non-positive numbers"
...
# This is provable and may be redundant.
assert abs( n*n - x ) < 0.00001
return n
有很多很多理由去做正式的断言。
18
如果优雅地处理不可能,那就来点戏剧性的
这是你代码的正确版本:
if filename.endswith('.jpg'):
# convert it to the PNG we want
try:
filename = convert_jpg_to_png_tmpfile(filename)
except PNGCreateError:
# Tell the user their jpg was crap
print "Your jpg was crap!"
在我看来,以下情况是合理的:
- 错误是完全、100%致命的,处理这个错误会让人感到太过沉重,难以理解
- 只有当某些事情导致逻辑法则改变时,断言才应该失败
否则,面对即将发生的事情,因为你可以预见到它。
ASSERT == "这绝不应该在现实中发生,如果发生了,我们就放弃"
当然,这和
#control should never get here
但我总是这样做
#control should never get here
#but i'm not 100% putting my money where my mouth
#is
assert(False)
是不同的。在你的例子中,我会使用if
版本,并把文件转换成jpg格式!
27
断言应该用来表达不变条件或前置条件。
在你的例子中,你是用它们来检查意外的输入,这其实是完全不同类型的错误处理。
根据需求,遇到错误输入时抛出异常并停止程序是完全可以的;不过代码应该写得更清晰明了,抛出一个AssertionError
并不够明确。
更好的做法是抛出你自己定义的异常,或者使用ValueError
。