断言False与断言false

时间:2017-08-07 09:02:53

标签: python python-2.7 assert

我最近的编码错误让我觉得......

我在其中一个功能中使用assert false代替assert False

仅在try/except子句中调用此函数。

所以我从未注意到这个"编译错误",直到我实际打印了异常的细节。

然后它让我想知道两者之间是否存在运行时差异。

当然," false"这里可以替换为任何其他未定义的符号。

显然,打印输出本身会有所不同。

这是我进行的一项简单测试:

try:
    assert false
except Exception,e:
    print "false: class name = {:15}, message = {}".format(e.__class__.__name__,e.message)

try:
    assert False
except Exception,e:
    print "False: class name = {:15}, message = {}".format(e.__class__.__name__,e.message)

此测试的打印输出为:

false: class name = NameError      , message = name 'false' is not defined
False: class name = AssertionError , message = 

所以我的问题是,这里有其他运行时差异吗?特别是,我很想知道使用assert(false)而非assert(False)是否会以某种方式妨碍我的计划的表现。

2 个答案:

答案 0 :(得分:2)

两个版本都是错误的,永远不会使用。

  • assert false, ...:永远不会达到assert语句,因为false表达式会引发NameError异常。在您的代码中有一个错误的气味,而不是代表您的故意行为。

    永远不要使用故意的错误来引发异常。您必须添加一条注释,解释为什么要对未来的代码维护者执行此操作,但是从来没有理由使用它,因为存在更好的替代方案。

  • assert False, ...:这是故意的断言失败,看起来像是试图调试而不是生产代码。如果断言没有成功,那么在之前的断言可能会失败。如果您需要在此时退出代码,引发异常

明确。提出例外。即使提出AssertionError exception也更好:

raise AssertionError('This should never be reached; boundary checks failed')

从你永远不应该使用的两个版本开始,在Python 3中assert(False, ...)“更快”,因为至少不会触发全局名称搜索。那是因为在Python 3中,False是一个关键字,因此编译器可以通过引用常量来优化它。但是,两者之间几乎没有实际差别。由于故意失败的断言应该按设计永远不会达到,或者最多到达一次,担心它们的表现是一个有争议的问题。

答案 1 :(得分:0)

这不是编译错误,两者都是运行时错误,显然存在差异:

评估false会产生一个NameError,这意味着您引用了一个未定义的名称。另一个代码路径可能会导致定义名称,在这种情况下,断言可能不会失败。这个简单的例子就是它上方的false = True语句(显然在另一种方式下会变得很糟糕,变量名称很差)。无论哪种方式,逻辑错误都是未定义名称的代码路径可以到达表达式。

断言False是一种强制AssertionError被抛出的方法。这是一个非常糟糕的技术,因为你添加了明确的代码失败,没有任何解释原因;我们无法解释错误,必须在代码中找到它以找出它发生的原因。断言应具有逻辑表达式和描述,以帮助进行调试。

无论哪种方式,您处理任何异常的方式都会丢失很多信息。特别是关于try错误发生的位置的任何内容。正常异常回溯(可以使用traceback.print_exception及其类似访问)包含此详细信息。

实际上,这种处理asserttry - catch的方式阻止您接收有关的任何错误的有用信息,但编译时错误除外SyntaxError和ImportError。

assert False的唯一明智用途我可以认为它可以测试assert语句本身。在所有正常使用中,我们都包括失败的条件。