python3断言_Python3 基础:断言assert

0、什么是断言(assertion)

断言是一个调试工具。它用于发现异常,而不是用于处理异常。

记住这句话,它是断言的核心意义。只有理解这句话,才能正确地使用断言。我们将会在最后一小节深入探讨这个问题。

Python3中,使用assert语法来声明一个断言,其语法格式如下:

assert bool_expr, optional_expr

如果bool_expr的估值(表达式的最终计算结果)为False,系统就会抛出一个AsesertionError异常。这个异常包含了必要的栈信息,所以它能够为解决这个“意外”提供很多的信息。

如果提供了可选的optional_expr,则optional_expr是异常AsesertionError的构造函数参数。optional_expr可为异常提供了额外的信息,所以它是非常有用的。

1、一个例子

我们知道,人类的生理性别只有两种,即男性和女性(No offence to GLBTQ)。假如我们定义了一个Human的类,其中有gender属性,那么这么属性必须是Male或者Female其中之一,而不能是其它值。程序在实际的运行过程中,gender属性偶尔会意外地被初始化为非法的值,那么在开发测试过程中,我们就可以使用assert语句来帮我们定位问题。

class Gender:

Male = 1 # 男

Female = 2 # 女

@classmethod

def IsValid(cls, val):

if val in (cls.Male, cls.Female):

return True

return Fale

class Human:

def __init__(self, name, age, gender):

self.name = name

self.age = age

self.gender = gender

assert Gender.IsValid(gedner), "Invalide Gender:{}".format(gender)

assert age >= 0, "Invalide age:{}".format(age)

在创建Human对象时,如果遇到意外性别或者年龄,程序就会抛出一个AsseritonError,并中断程序(如果没有捕获处理的话)。

2、怎么关闭assert

正如第0节所说的,assertion是一个调试工具,在功能开发并测试完毕之后,正式发布之前,应该先把assertion语句全部去掉(或者使其失效)。在C++中,assert语句在release版本中是一个空语句,在编译阶段就可以被处理。但在Python3是脚本语言,所以我们需要用不同的方式来处理。

第一种是通过给python解析器传递-O参数,其实命令形式如下:

python -O program.py

另外一种,也是比较直观和暴力的方法,就是直接注释(或者删除)所有的assert语句。

3、如何用好assert(assert的目的)

断言是一个调试工具。它用于发现异常,而不是用于处理异常。

我们公司有一个C++面试题,其内容大概如下:

// 实现函数ReverseStr,将参数str所代表的字符串反转void ReverseStr(char * str);

其中大概有10%的面试者会在第一行代码就直接用一个assert语句,来判断str是否为NULL。其代码大抵如下:

void ReverseStr(char * str)

{

assert(NULL != str);

// 其余代码

}

而当我问其为什么使用assert,而不是一个if语句的时候,没有人能给出正确的解释。不过结果也不出意思,能在此处使用assert的人,就说明他不理解assert是什么。这也是我为什么会增加这一个小节内容的原因。

在实际开发过程中,难免会出现一些意想不到的问题。有些问题会产生严重的后果,产生非常易于发现的错误,或者直接使程序挂掉。这种越noisy的错误,越容易被发现,往往也越容易处理。但一些错误,它并不会产生明显的错误,往往程序也能“正常地”继续执行;而往往就是这类错误,会让人崩溃。

异常处理是程序开发过程中非常正常的形象。但是,如果无论什么地方都进行异常处理,程序就会显得非常庞大而冗余,而且没有必要。我们会在确保一定会出错(被错误使用)的地方做异常处理;而那些逻辑上(理论上、设计上)不会出错的地方,就不需要。

而我们使用assert的大部分时候,就是用来监测那些逻辑上不会出错的地方可能发生的异常。如果监测到了,应该是修改设计,修复BUG,或者增加必要的异常处理。

所以我们使用assert,是用来发现意料之外的异常,而不是用来做异常处理。也就是说,这是一个使用意料之外的错误noisy的工具。如果我们定位到了问题,应该进行功能或者设计上的修改,来修复这个问题。

我们现回头看看本节开头提到的问题,“上纲上线”地讨论一下aasert到底应该怎么使用。由于C++中assert的目的与Python的一致,为了方便讨论,这里直接使用了C++代码。

void ReverseStr(char *str)

{

if (NULL == str)

{

// str传入NULL,是一个意料之中的“错误”,我们应该直接处理它

// 严格意义上来说,这个处理也是功能的一部分

return;

}

int len = strlen(str);

// 如果一个字符串的长度过长,可能会是一个错误,其中有种可能是str未以0结尾;

// 或者由于其它不可描述的原因导致

// 如果逻辑上,len不可能大于10240,但莫名地出现这种情况,我们就可以使用asser来定位问题了

// 在release版本中,下面的语句将会是一个空语句,因为它不是这个函数实现的一部分。

assert(len < 10240);

// 余下的代码

}

在这个例子中,if语句用于“错误”(异常)处理,它是功能的一部分,会一直存在。而assert语句用于发现异常,在我们解决了这个异常之后,我们就会让assert语句失效(去掉代码,或者借助于编译器)。

4、多说一句

assert是调试工具之一,而非全部。

每个类型的问题,会用到不同类型的调试工具。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值