python基础(part14)--异常处理

鄙人学习笔记
开发工具:Spyder



异常处理

我们先以一个例子为开头

代码:

控制台输入5,则正常运行:

但如果我们输入xxx, 那么回怎样呢:

python会报错!出现ValueErroe错误.

如果我们输入0,有会怎样呢:

python又报错了!出现ZeroDivisionErroe错误

备注:如果代码出现错误,那么发生错误之后的代码,则不会运行(”后续逻辑…….”没有被打印)

异常

  • 定义

异常就是运行时检测到的错误(在有些语言中,比如JAVA,错误和异常是有明确区别的. 但在python中异常和错误的界定不清晰, 我们则可以说错误是一种异常)。

  • 现象

当运行时,程序不会再向下执行,而转到函数的调用语句

比如:

  • 常见的异常类型

名称异常(NameError):变量未定义。
类型异常(TypeError):不同类型数据进行运算。
索引异常(IndexError):超出索引范围。
属性异常(AttributeError):对象没有对应名称的属性。
键异常(KeyError):没有对应名称的键。
为实现异常(NotImplementedError):尚未实现的方法。

备注:Exception类为异常基类,是其他所有异常类的父类.

异常处理

为了不让异常影响到之后的程序运行,我们就需要进行异常的处理,“让异常变为正常”。

  • 语法
try:
    可能触发异常的语句
except 错误类型1 [as 变量1]:
    处理语句1
except 错误类型2 [as 变量2]:
    处理语句2
except Exception  [as 变量3]:
    不是以上错误类型的处理语句
else:
    未发生异常的语句
finally:
无论是否发生异常的语句

  • 作用

将程序由异常状态转为正常流程。

  • 说明
子句 含义
as子句 是用于绑定错误对象的变量,可以忽略
except子句 该子句可以有一个或多个,用来捕获某种类型的错误
else子句 该子句最多只能有一个
finally子句 该子句最多只能有一个,如果没有except子句,该子句就必须存在

举个例子1

代码:

异常处理:

在这里插入图片描述

运行, 并在控制台输入ss


由结果可知,经过异常处理后,我们将发生的异常打印的出来,并执行了后面的代码。

如果我们修改一下处理语句,如下所示:

运行一下, 并在控制台先输入xx, 异常被处理后,再故意输入ff

结果会怎样呢?

会报错!这是因为当person_count = int(input(“请输入人数:”))语句又发生异常时,它找回了调用它的语句div_apple(10)注意:是except下的div_apple(10)),python发现并没有 try-except的异常处理语句帮他处理,于是他就报错了。

Exception类可以捕获到所有类型的异常。但是如果只写它,我们就不能对具体错误,做出相应的处理逻辑。

如果我们再修改一下处理语句,如下所示:

我们试着运行一下, 并在控制台输入0

我们再运行一下, 并在控制台输入af


这样我们就可以对症下药,对具体错误,做出相应的处理。

但是,我们可能不会预测到所有会发生的错误。这时,我们就可以,在末尾加一个Exception捕获剩余错误。

我们修改一下处理语句:

这样就可以既做到对症下药,又做到面面俱到。

举个例子2

我们在处理语句中增加一个else(当没有发生异常时,执行的语句):

我们再运行一下, 并在控制台输入4


除此之外,还有一个关键字finally(不管有没有异常都执行), 我们测试一下:

我们先在控制台输入一个有错的f

我们再在控制台输入一个没错的4


但是我们要是把print(“无论是否发生异常, 都执行的逻辑”)写在处理异常的语句之外(详见下图),这句话也可以执行,那么这个finally到底有啥用呢?

请听下回分解!

raise语句

  • 作用

抛出一个错误,让程序进入异常状态。

  • 目的

在程序调用层数较深时,向主函数传递错误信息要层层retrun比较麻烦(或者干脆就不能写return)。所以,可以人为抛出异常,直接传递错误信息。

  • 图示

假如我们有一个方法fun01,它调用了方法fun02, fun02调用了方法fun03, fun03调用了方法fun04。当我们想用fun04向fun01传递一个信息时,可以层层return,一层一层的传递数据:

但是我们也可以用fun04人为抛出一个异常,直接把信息传递给fun01:

案例

我们创建一个Bunny类,如果创建的Bunny对象的age不符合,大于等于0且小于等于5的要求,我们就抛出异常。

代码:

class Bunny:
    __slots__ = ("__age")
    def __init__(self, age):
        self.age = age
        
    @property
    def age(self):
        return self.__age
    
    @age.setter
    def age(self, value):
        if 0 <= value <= 5:
            self.__age = value
        else:
            raise ValueError("非幼年")

try:
    b01 = Bunny(6)
    print(b01.age)

except Exception as e:
    print(e)

结果:

自定义异常

如果python提供的异常类型,并不满足我们的需求,我们就可以自定义异常。

  • 语法

定义自定义异常:

class 类名Error(Exception):
		def __init__(self,参数):
			super().__init__(参数)
			self.数据 = 参数

调用自定义异常:

try:
    ...
    raise 自定义异常类名(参数)
    ...
except 定义异常类 as 变量名:
    变量名.数据
  • 作用

封装错误信息

案例

我们在上面一个案例中借用了ValueError异常类型,人为抛出异常,但是我们觉得,并不能满足我们的需求,我们想自己创建一个专用的异常类,抛出错误信息。

创建异常类:

class AgeError(Exception):
    
    def __init__(self, msg, age_value):
        super().__init__(msg)
        self.age_value = age_value

备注:msg表示错误的信息[这是一定要传的参数,并且要传给父类的构造方法], 我们还可以自己传一些想传递的信息,比如:age_value错误的年龄

调用自定义异常类:

class Bunny:
    __slots__ = ("__age")
    def __init__(self, age):
        self.age = age
        
    @property
    def age(self):
        return self.__age
    
    @age.setter
    def age(self, value):
        if 0 <= value <= 5:
            self.__age = value
        else:
            raise AgeError("非幼年", value)

创建Bunny类,并处理异常,打印出,异常信息:

try:
    b01 = Bunny(6)
    print(b01.age)

except AgeError as e:
    print(e.args)
    print(e.age_value)

结果:

发布了116 篇原创文章 · 获赞 22 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/m0_37422217/article/details/105145322