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?
当前回答
英语单词assert在这里的意思是发誓、肯定、宣称。它的意思不是“检查”或“应该是”。这意味着你作为一个程序员要在这里做一个宣誓声明:
# I solemnly swear that here I will tell the truth, the whole truth,
# and nothing but the truth, under pains and penalties of perjury, so help me FSM
assert answer == 42
如果代码是正确的,除了单事件中断、硬件故障等,任何断言都不会失败。这就是为什么程序对终端用户的行为不能受到影响。特别是,断言即使在异常的编程条件下也不能失败。这种事从来没有发生过。如果发生这种情况,程序员应该为此受到惩罚。
其他回答
当x在整个函数中小于零时,能够自动抛出错误。您可以使用类描述符。这里有一个例子:
class LessThanZeroException(Exception):
pass
class variable(object):
def __init__(self, value=0):
self.__x = value
def __set__(self, obj, value):
if value < 0:
raise LessThanZeroException('x is less than zero')
self.__x = value
def __get__(self, obj, objType):
return self.__x
class MyClass(object):
x = variable()
>>> m = MyClass()
>>> m.x = 10
>>> m.x -= 20
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "my.py", line 7, in __set__
raise LessThanZeroException('x is less than zero')
LessThanZeroException: x is less than zero
"assert"语句在编译优化时被删除。所以,是的,它们在性能和功能上都有差异。
在编译时请求优化时,当前代码生成器不会为assert语句生成代码。Python 3 Docs
如果您使用assert来实现应用程序功能,然后优化部署到生产环境,那么您将受到“但它在开发中有效”缺陷的困扰。
参见PYTHONOPTIMIZE和-O -OO
如前所述,当您的代码should NOT到达某个点(意味着那里存在错误)时,应该使用断言。在我看来,使用断言最有用的原因可能是不变量/前置/后置条件。在循环或函数的每次迭代的开始或结束时,这些必须为真。
例如,一个递归函数(两个独立的函数,一个处理错误的输入,另一个处理错误的代码,因为它很难与递归区分开来)。如果我忘记写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
这些循环不变量通常可以用断言表示。
Assert是检查- 1. 有效条件, 2. 有效的表述, 3.真正的逻辑; 源代码。它不会让整个项目失败,而是会发出警报,提示源文件中有些地方不合适。
在例1中,因为变量'str'不是空的。因此不会引发任何断言或异常。
示例1:
#!/usr/bin/python
str = 'hello Python!'
strNull = 'string is Null'
if __debug__:
if not str: raise AssertionError(strNull)
print str
if __debug__:
print 'FileName '.ljust(30,'.'),(__name__)
print 'FilePath '.ljust(30,'.'),(__file__)
------------------------------------------------------
Output:
hello Python!
FileName ..................... hello
FilePath ..................... C:/Python\hello.py
在例2中,var 'str'为空。因此,我们可以通过assert语句来避免用户走在错误程序前面。
示例2:
#!/usr/bin/python
str = ''
strNull = 'NULL String'
if __debug__:
if not str: raise AssertionError(strNull)
print str
if __debug__:
print 'FileName '.ljust(30,'.'),(__name__)
print 'FilePath '.ljust(30,'.'),(__file__)
------------------------------------------------------
Output:
AssertionError: NULL String
当我们不想调试并意识到源代码中的断言问题时。禁用优化标志
python -O assertStatement.py 没有东西会被打印出来
assert的四个目的
假设您与四位同事Alice、Bernd、Carl和Daphne一起处理20万行代码。 他们喊你的代码,你喊他们的代码。
那么assert有四个角色:
Inform Alice, Bernd, Carl, and Daphne what your code expects. Assume you have a method that processes a list of tuples and the program logic can break if those tuples are not immutable: def mymethod(listOfTuples): assert(all(type(tp)==tuple for tp in listOfTuples)) This is more trustworthy than equivalent information in the documentation and much easier to maintain. Inform the computer what your code expects. assert enforces proper behavior from the callers of your code. If your code calls Alices's and Bernd's code calls yours, then without the assert, if the program crashes in Alices code, Bernd might assume it was Alice's fault, Alice investigates and might assume it was your fault, you investigate and tell Bernd it was in fact his. Lots of work lost. With asserts, whoever gets a call wrong, they will quickly be able to see it was their fault, not yours. Alice, Bernd, and you all benefit. Saves immense amounts of time. Inform the readers of your code (including yourself) what your code has achieved at some point. Assume you have a list of entries and each of them can be clean (which is good) or it can be smorsh, trale, gullup, or twinkled (which are all not acceptable). If it's smorsh it must be unsmorshed; if it's trale it must be baludoed; if it's gullup it must be trotted (and then possibly paced, too); if it's twinkled it must be twinkled again except on Thursdays. You get the idea: It's complicated stuff. But the end result is (or ought to be) that all entries are clean. The Right Thing(TM) to do is to summarize the effect of your cleaning loop as assert(all(entry.isClean() for entry in mylist)) This statements saves a headache for everybody trying to understand what exactly it is that the wonderful loop is achieving. And the most frequent of these people will likely be yourself. Inform the computer what your code has achieved at some point. Should you ever forget to pace an entry needing it after trotting, the assert will save your day and avoid that your code breaks dear Daphne's much later.
在我看来,assert的两个文档目的(1和3)和 保障措施(2和4)同样有价值。 告知人民甚至可能比告知计算机更有价值 因为它可以防止assert要捕捉的错误(在情况1中) 无论如何,接下来还有很多错误。
推荐文章
- 如何以编程方式获取python.exe位置?
- 如何跳过循环中的迭代?
- 使用Pandas为字符串列中的每个值添加字符串前缀
- ImportError:没有名为matplotlib.pyplot的模块
- 在python中遍历对象属性
- 如何在Python中使用方法重载?
- 在Python中提取文件路径(目录)的一部分
- 如何安装没有根访问权限的python模块?
- 尝试模拟datetime.date.today(),但不工作
- 将行添加到数组
- 如何在Python中直接获得字典键作为变量(而不是通过从值搜索)?
- Python:为什么functools。部分有必要吗?
- 如何用python timeit对代码段进行性能测试?
- Python迭代器中的has_next ?
- ConfigParser中的列表