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?
当前回答
我补充说,我经常使用断言来指定属性,比如循环不变量或我的代码应该具有的逻辑属性,就像我在正式验证的软件中指定它们一样。
它们有两个目的,告诉读者,帮助我推理,并检查我在推理中没有犯错误。例如 :
k = 0
for i in range(n):
assert k == i * (i + 1) // 2
k += i
#do some things
或者在更复杂的情况下:
def sorted(l):
return all(l1 <= l2 for l1, l2 in zip(l, l[1:]))
def mergesort(l):
if len(l) < 2: #python 3.10 will have match - case for this instead of checking length
return l
k = len(l // 2)
l1 = mergesort(l[:k])
l2 = mergesort(l[k:])
assert sorted(l1) # here the asserts allow me to explicit what properties my code should have
assert sorted(l2) # I expect them to be disabled in a production build
return merge(l1, l2)
因为当python在优化模式下运行时,断言是禁用的,所以不要犹豫在它们中编写代价高昂的条件,特别是当它使您的代码更清晰,更不容易出现错误时
其他回答
"assert"语句在编译优化时被删除。所以,是的,它们在性能和功能上都有差异。
在编译时请求优化时,当前代码生成器不会为assert语句生成代码。Python 3 Docs
如果您使用assert来实现应用程序功能,然后优化部署到生产环境,那么您将受到“但它在开发中有效”缺陷的困扰。
参见PYTHONOPTIMIZE和-O -OO
当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
除了其他答案之外,断言本身也会抛出异常,但仅抛出AssertionErrors。从实用主义的角度来看,当您需要对捕获的异常进行精细控制时,断言并不适合。
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 没有东西会被打印出来
这种方法唯一真正的错误是,很难使用断言语句产生非常描述性的异常。如果你正在寻找更简单的语法,记住你也可以这样做:
class XLessThanZeroException(Exception):
pass
def CheckX(x):
if x < 0:
raise XLessThanZeroException()
def foo(x):
CheckX(x)
#do stuff here
另一个问题是,使用assert进行正常的条件检查会使使用-O标志禁用调试断言变得困难。
推荐文章
- Numpy Max vs amax vs maximum
- 我应该在.gitignore文件中添加Django迁移文件吗?
- 每n行有熊猫
- 实例属性attribute_name定义在__init__之外
- 如何获取在Python中捕获的异常的名称?
- 第一次出现的值大于现有值的Numpy
- 如何从Python函数中返回两个值?
- 前一个月的Python日期
- Python中方括号括起来的列表和圆括号括起来的列表有什么区别?
- Python日志记录不输出任何东西
- 每n秒运行特定代码
- SQLAlchemy是否有与Django的get_or_create等价的函数?
- 如何将python datetime转换为字符串,具有可读格式的日期?
- 美丽的汤和提取div及其内容的ID
- 断言是邪恶的吗?