python 断言详细讲解用法及其案例_Python断言的最佳实践

回答(13)

avatar.png

2 years ago

当x在整个函数中变得小于零时能够自动抛出错误 . 你可以使用class descriptors . 这是一个例子:

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 "", line 1, in

File "my.py", line 7, in __set__

raise LessThanZeroException('x is less than zero')

LessThanZeroException: x is less than zero

avatar.png

2 years ago

断言应该用于测试不应该发生的条件 . 目的是在程序状态损坏的情况下尽早崩溃 .

异常应该用于可能发生的错误,并且 you should almost always create your own Exception classes .

例如,如果您正在编写一个函数以从配置文件读取到 dict ,则文件中的格式不正确应该引发 ConfigurationSyntaxError ,而您可以 assert 表示您不打算返回 None .

在您的示例中,如果 x 是通过用户界面或外部源设置的值,则最好是例外 .

如果 x 仅由您自己的代码在同一程序中设置,请使用断言 .

avatar.png

2 years ago

"assert" statements are removed when the compilation is optimized . 所以,是的,有性能和功能差异 .

当在编译时请求优化时,当前代码生成器不会为assert语句发出任何代码 . - Python 2.6.4 Docs

如果您使用 assert 来实现应用程序功能,然后将部署优化到 生产环境 ,您将受到"but-it-works-in-dev"缺陷的困扰 .

avatar.png

2 years ago

断言的四个目的

假设您与四位同事Alice,Bernd,Carl和Daphne一起处理了200,000行代码 . 他们调用你的代码,你调用他们的代码 .

然后 assert 有 four roles :

Inform Alice, Bernd, Carl, and Daphne what your code expects.

假设您有一个处理元组列表的方法,如果这些元组不是不可变的,程序逻辑可能会中断:

def mymethod(listOfTuples):

assert(all(type(tp)==tuple for tp in listOfTuples))

这比文档中的等效信息更可靠,更易于维护 .

Inform the computer what your code expects.

assert 强制执行代码调用者的正确行为 . 如果你的代码调用Alices 's and Bernd' s代码调用你的,那么没有 assert ,如果程序在Alices代码崩溃,Bernd可能会认为这是Alice的错,Alice调查并可能认为这是你的错,你调查并告诉Bernd它在事实上他的 . 失去了很多工作 .

有了断言,无论谁接到错误的电话,他们很快就会发现这是他们的错,而不是你的错 . 爱丽丝,伯恩德,你们都受益匪浅 . 节省了大量的时间 .

Inform the readers of your code (including yourself) what your code has achieved at some point.

假设你有一个条目列表,每个条目都可以是干净的(这很好),或者它可以是smorsh,trale,gullup或者闪烁(这些都是不可接受的) . 如果它必须是baludo;它必须是baludoed;如果它闪烁,它必须再次闪烁,除了星期四 . 你明白这个想法:这很复杂 . 但最终结果是(或应该)所有条目都是干净的 . Right Thing(TM)要做的是总结清洁循环的效果

assert(all(entry.isClean() for entry in mylist))

对于每个试图理解精彩循环实现的确切内容的人来说,这个陈述让人头疼 . 而这些人中最常见的可能就是你自己 .

Inform the computer what your code has achieved at some point.

如果您在小跑之后忘记调整需要它的条目, assert 将节省您的一天,并避免您的代码打破亲爱的Daphne's晚了 .

在我看来,文件(1和3)和保障(2和4)的两个目的同样有 Value .

告知人们甚至可能比告知计算机更有 Value ,因为它可以防止出现的错误(案例1)以及随后的大量错误 .

avatar.png

2 years ago

除了其他答案之外,断言本身会抛出异常,但只会抛出AssertionErrors . 从功利主义的角度来看,当你需要精细控制你捕获的异常时,断言不适合 .

avatar.png

2 years ago

_606519很难用assert语句做出非常具有描述性的异常 . 如果您正在寻找更简单的语法,请记住您也可以这样做:

class XLessThanZeroException(Exception):

pass

def CheckX(x):

if x < 0:

raise XLessThanZeroException()

def foo(x):

CheckX(x)

#do stuff here

另一个问题是使用assert进行正常条件检查是因为它很难使用-O标志禁用调试断言 .

avatar.png

2 years ago

如前所述,当您的代码不应达到某一点时,应使用断言,这意味着存在错误 . 我可以看到使用断言的最有用的原因可能是一个不变/前/后条件 . 这些在循环或函数的每次迭代的开始或结束时必须是真的 .

例如,递归函数(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

这些循环不变量通常可以用断言表示 .

avatar.png

2 years ago

英语单词 assert 在这里用于 swear , affirm , avow . 这并不意味着"check"或"should be" . 这意味着你作为一名程序员在这里制作一个 sworn statement :

# 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

如果代码正确,则禁止Single-event upsets,硬件故障等, no assert will ever fail . 这就是为什么程序对最终用户的行为不得受到影响的原因 . 特别是,即使在 exceptional programmatic conditions 下,断言也不会失败 . 它永远不会发生 . 如果它发生了,那么程序员应该为之奋斗 .

avatar.png

2 years ago

是否存在性能问题?

请记住 "make it work first before you make it work fast" .

任何程序的百分之几通常与其速度相关 . 如果它被证明是一个性能问题,你总是可以踢出或简化 assert - 而且大部分都不会 .

Be pragmatic :

假设您有一个处理非空元组列表的方法,如果这些元组不是不可变的,程序逻辑将会中断 . 你应该写:

def mymethod(listOfTuples):

assert(all(type(tp)==tuple for tp in listOfTuples))

如果您的列表往往长达十个条目,这可能很好,但如果它们有一百万个条目,它可能会成为一个问题 . 但不是完全丢弃这个有 Value 的支票,你可以简单地将其降级为

def mymethod(listOfTuples):

assert(type(listOfTuples[0])==tuple) # in fact _all_ must be tuples!

这很便宜,但无论如何都可能会捕获大部分实际程序错误 .

avatar.png

2 years ago

有一个名为JBoss Drools的框架,用于执行运行时监控以断言业务规则,该问题回答了问题的第二部分 . 但是,我不确定是否有这样的python框架 .

avatar.png

2 years ago

断言是检查 -

1. the valid condition, 2. the valid statement, 3. true logic; 源代码 . 它不会使整个项目失败,而是会在源文件中发出不适合的警报 .

在示例1中,因为变量'str'不是nul . 因此,不会引发任何断言或异常 .

Example 1:

#!/usr/bin/python

str = 'hello Pyhton!'

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 Pyhton!

FileName ..................... hello

FilePath ..................... C:/Python\hello.py

在示例2中,var 'str'是nul . 所以我们通过 assert 语句来保存用户免于错误的程序 .

Example 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

什么都不会打印

avatar.png

2 years ago

在诸如PTVS,PyCharm之类的IDE中,Wing assert isinstance() 语句可用于为某些不清楚的对象启用代码完成 .

avatar.png

2 years ago

如果您正在处理依赖 assert 正常运行的遗留代码,即使it should not,那么添加以下代码是一个快速修复,直到您找到时间重构:

try:

assert False

raise Exception('Python Assertions are not working. This tool relies on Python Assertions to do its job. Possible causes are running with the "-O" flag or running a precompiled (".pyo" or ".pyc") module.')

except AssertionError:

pass

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值