使用
assert
作为标准代码的一部分而不是仅仅用于调试目的,是否存在性能或代码维护问题?是
assert x >= 0, 'x is less than zero'
好或坏比
if x < 0: raise Exception, 'x is less than zero'
另外,有没有办法设置业务规则,
if x < 0 raise error
总是在没有try/except/finally
情况下检查,如果在整个代码x
任何时候小于0都会引发错误,就像你在函数开始时设置assert x < 0
,函数中x
变得小于0的任何地方都会引发异常?
#1楼
如前所述,当您的代码不应该达到某一点时,应该使用断言,这意味着存在错误。 我可以看到使用断言的最有用的原因可能是一个不变/前/后条件。 这些在循环或函数的每次迭代的开始或结束时必须是真的。
例如,一个递归函数(2个单独的函数,因此1处理错误的输入,另一个处理错误的代码,导致很难用递归区分)。 如果我忘记编写if语句,那会出现问题。
def SumToN(n):
if n <= 0:
raise ValueError, "N must be greater than or equal to 0"
else:
return RecursiveSum(n)
def RecursiveSum(n):
#precondition: n >= 0
assert(n >= 0)
if n == 0:
return 0
return RecursiveSum(n - 1) + n
#postcondition: returned sum of 1 to n
这些循环不变量通常可以用断言表示。
#2楼
优化编译时,将删除“assert”语句 。 所以,是的,有性能和功能差异。
在编译时请求优化时,当前代码生成器不会为assert语句发出任何代码。 - Python 2.6.4 Docs
如果您使用assert
来实现应用程序功能,然后将部署优化到生产,您将会受到“但它在工作中开发”缺陷的困扰。
#3楼
除了其他答案之外,断言本身会抛出异常,但只会抛出AssertionErrors。 从功利主义的角度来看,当你需要对你捕获的异常进行细粒度控制时,断言是不适合的。
#4楼
assert
的四个目的
假设您与四位同事Alice,Bernd,Carl和Daphne一起处理了200,000行代码。 他们调用你的代码,你调用他们的代码。
然后assert
有四个角色 :
告知Alice,Bernd,Carl和Daphne您的代码所期望的内容。
假设您有一个处理元组列表的方法,如果这些元组不是不可变的,程序逻辑可能会中断:def mymethod(listOfTuples): assert(all(type(tp)==tuple for tp in listOfTuples))
这比文档中的等效信息更可靠,更易于维护。
通知计算机代码期望的内容。
assert
强制执行代码调用者的正确行为。 如果你的代码调用Alices和Bernd的代码调用你的代码,那么没有assert
,如果程序在Alices代码崩溃,Bernd可能会认为这是Alice的错,Alice调查并可能认为这是你的错,你调查并告诉Bernd它在事实上他的。 失去了很多工作。
有了断言,无论谁接到电话都是错误的,他们很快就会发现这是他们的错,而不是你的错。 爱丽丝,伯恩德,你们都受益匪浅。 节省了大量的时间。告诉读者您的代码(包括您自己)在某些时候代码所取得的成就。
假设你有一个条目列表,每个条目都可以是干净的(这很好),或者它可以是smorsh,trale,gullup或者闪烁(这些都是不可接受的)。 如果它是smorsh它必须是unmorshed; 如果它是trale它必须是baludoed; 如果它是gullup它必须小跑(然后也可能节奏); 如果它闪烁,它必须再次闪烁,除了星期四。 你明白这个想法:这很复杂。 但最终结果是(或应该)所有条目都是干净的。 Right Thing(TM)要做的是总结清洁循环的效果assert(all(entry.isClean() for entry in mylist))
对于每个试图理解精彩循环实现的确切内容的人来说,这个陈述让人头疼。 而这些人中最常见的可能就是你自己。
告知计算机您的代码在某些时候已经实现了什么。
如果您在小跑之后忘记调整需要它的条目,那么assert
将节省您的一天,并避免您的代码在Daphne之后发生。
在我看来, assert
文件(1和3)和保障(2和4)的两个目的同样有价值。
告知人们甚至可能比告知计算机更有价值,因为它可以防止assert
旨在捕获的错误(在案例1中)以及在任何情况下的大量后续错误。
#5楼
是否存在性能问题?
请记住“在你快速工作之前先让它工作” 。
任何程序的百分之几通常与其速度相关。 如果它被证明是一个性能问题,你总是可以踢出或简化assert
- 而且大多数assert
都不会。务实 :
假设您有一个处理非空元组列表的方法,如果这些元组不是不可变的,程序逻辑将会中断。 你应该写:def mymethod(listOfTuples): assert(all(type(tp)==tuple for tp in listOfTuples))
如果您的列表往往长达十个条目,这可能很好,但如果它们有一百万个条目,它可能会成为一个问题。 但是,不要完全丢弃这个有价值的支票,你可以简单地将其降级为
def mymethod(listOfTuples): assert(type(listOfTuples[0])==tuple) # in fact _all_ must be tuples!
这很便宜,但很可能会捕获大部分实际程序错误。
来源:oschina
链接:https://my.oschina.net/stackoom/blog/3161481