Python防御式编程


背景

当编写Python代码时,我们对不可预料的程序问题提前进行预防,使得输入(输出)数据潜在的错误和异常能够被及时找出并处理,保证主程序不受影响,而这种预防动作就是防御式编程(Defensive Programming),它是在实际工程中常用的一种手段。

下面将介绍几种Python中常见的防御式编程的示例,涵盖了raisetry-exceptassert 等概念。这些预防机制一般用在:输入验证、异常处理、边界条件检查等场景

1. 使用raise抛出异常

如下例子,在除法函数 divide 中,当判断到除数 b==0 时,触发 raise 抛出ZeroDivisionError异常,并提示说“除数不能为零”,当程序运行至抛出错误后,终止运行。

def divide(a, b):
	if b == 0:
		raise ZeroDivisionError("除数不能为零")
	return a / b
ZeroDivisionError: 除数不能为零

2. 使用try捕获和处理异常

有时候我们希望异常发生时,代码还能继续运行,可能是输出错误信息,也可能是往另外的代码分支运行,总之不希望代码因为错误而直接停止时,可以考虑用 try - except

(1)捕获和处理指定异常类型

以下示例演示了用 try 运行一段会报错的代码,被捕捉到 ZeroDivisionError 错误后,代码继续运行,输出后续的内容。

def divide(a, b):
	if b == 0:
		raise ZeroDivisionError("除数不能为零")
	return a / b

try:
	value_ = divide(2, 0)
except ZeroDivisionError as e:
	print(f"Exception caught: {e}")
	value_ = 0
print("Continuing with the program...")
print("Result: ", value_)

打印的结果为:

Exception caught: 除数不能为零
Continuing with the program...
Result:  0

(2)捕获和处理多个异常类型

进一步地,当我们知道某段代码可能会报错的几种类型,但不确定具体是哪一类,此时可以多写几层 except 来捕获多种异常类型。

如下例子:

try:
    file = open("example.txt", "r")
    content = file.read()
    file.close()
except FileNotFoundError:
    print("文件不存在")
except PermissionError:
    print("无权限访问文件")

该例子首先尝试打开和读取文件内容,不论哪一句代码发生错误,都会抛出异常,此时被 except 进行捕获,当判断是第一类错误FileNotFoundError时,则打印“文件不存在”,当判断为第二类错误PermissionError,则返回“无权限访问文件”。

(3)使用finally子句清理资源

try-except 结构中,常常会看到最后还有finally,不论前面的 try 是否发生异常,finally 下的代码均会被执行。其实也可以像前面捕获除法错误的代码一样,通过缩进来控制比会被执行的代码块。

在必执行的代码块中,常常存放着一些清理资源、关闭文件等功能的语句。例如,上面的例子在 try 中打开了相应的文本,如果没报错,此时就需要在使用后将 open 的资源释放,可以通过下面的语句:

if 'file' in locals():
	file.close()

上述语句通过判断局部作用域是否有 file 变量,如果有说明文件被打开,此时则把相应的文件关闭。

3. 使用assert进行断言

类似于运行 raise 会抛出错误一样,断言 assert 可以检验相应的约束是否成立,如果成立,则代码继续,如果不成立,则抛出AssertionError错误。

如下例子:

def validate_age(age):
    assert age >= 0, "年龄不能为负数"
    assert age < 150, "年龄无效"

try:
    validate_age(-10)
except AssertionError as e:
    print("断言失败:", str(e))

上述例子在 validate_age 函数中增加了两个断言,即传入的年龄需要大于 0 且小于 150,否则抛出 AssertionError 错误。当输入 -10 时,第一个断言判断不通过,返回报错信息,信息被 except 捕获并做出相应处理。

4. 总结

由于Python不是强类型语言,在定义变量的时候并不申明变量类型,此外,有时候我们程序进行一定的操作之前需要检查输入(输出)数据的正确性,这时候我们会写一些防御性代码进行判断,以更好地处理错误和异常情况,增加代码的健壮性和可靠性。

但同时需要注意的是,大量的异常判断有时候会降低代码性能,因此需要权衡进行异常判断的关键位置。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lins号丹

小小鼓励,满满动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值