Python的`assert`语句有哪些可接受的使用场景?

31 投票
8 回答
11887 浏览
提问于 2025-04-15 18:30

我经常使用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!"

在我看来,以下情况是合理的:

  1. 错误是完全、100%致命的,处理这个错误会让人感到太过沉重,难以理解
  2. 只有当某些事情导致逻辑法则改变时,断言才应该失败

否则,面对即将发生的事情,因为你可以预见到它。

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

撰写回答