粉丝14获赞148

拍摄零基础入门,那这节视频我们来了解一下异常它的各种类型,这节视频是我系列视频当中的第六十一期,在 上节视频当中呢,我有提到说我们自己写的文件当中,如果有错误,我们可以通过 rate 来生成一个异常对象进行抛出。 在使用我这个文件的其他文件当中,可以通过 try accept 来捕获这个异常对象,然后呢再根据这个异常对象做相应的处理。 那这节视频为了方便讲解呢,我直接把抛出异常对象这个代码写在这个 try 下边啊,那这样呢,我就不用说呃,两个文件来回的去说了啊,因为这节视频我们主要就说这个语法, 在上节视频当中呢,我们这个语法就是现在我们看到的这个样子。那接下来呢,我想再给它加一点啊,就是在 except 后边加了一个 exception 啊,这个 exception 是 类,它的意思是说 你 try 下边执行一些代码,然后我再 accept。 啊,就是最后这个红字这个代码段呢,我尝试去捕获这个错误,捕获这个异常对象, 如果这个异常对象它是由 exception 这个类实体化出来的,或者是由 exception 这个类的子类 或者是子孙类实力化出来的对象。好,那符合这个要求,那我就把它捕获到,捕获到之后呢,我做相应的处理, 这是后边加 exception 它的意思啊。好,那在上节视频当中呢,我并没有加这个 exception, 其实呢,它默认啊,我不写就是 except, 后边冒号我啥都不写,其实默认就是 exception 了啊,所以在这我写不写都是一样,在这我只是想把它明确出来, 当然后边呢,还可以再写上一个 s e, 这个 e 就是 我真正的捕获到异常对象那个对象啊,那假使说我们现在这个代码在 try 下边,也就是三行代码中间啊,中间第二行这个代码,我不是十六画出一个对象瑞字吗?哎,就是抛出异常,好,那这是一个异常对象。 哎,那我们下边呢?呃,第三行代码捕获到这个异常对象啊,这个对象就用 e 来表示它。好,那简要说明呢,在这说我捕获到这个异常对象了,哎,我可以做我自己的处理啊,我们也可以针对这个异常对象啊,因为异常对象里边有 你这个错误是从哪个文件里边抛出来的,大概是在第几行抛出来的啊?相应的这些信息,我们真实代码当中可能会根据这个异常对象做更具体的处理啊,因为我在这只是讲解语法,所以呢,哎,语法呢,暂时就这个样子啊。好, 那接下来啊,接下来我们这节课的重点,那就是说我们说 exception 是 异常的意思,是错误的意思,但是你说它是错误的意思吧,太笼统了啊,那什么错误呢?哎,我们 python 语言呢啊,可以把这个错误给 它细分了很多种啊,当然 exception 是 类,那细分出来的很多错误,它其实也是类啊,从,呃编程语言上来说,它是一个类的形式啊。好,在这呢,呃,我们就具体的来认识一下这个错误类型,或者说是异常类的类型啊。 好,呃,那我们可以说是顶层,其实它不是绝对的顶层啊。 exception 啊,这是一个啊,所有错误类,几乎所有错误类的顶层类啊,然后呢?呃,在它的下边,不,不是说它的直接子类啊,可能是它子类的子类啊,总之它们有继承关系。 第一个我要说的也是我们这个蟒蛇书当中第一个介绍的叫 zero division ever, 它三个单词,第一个单词 z e r o zero, 那 就是零,然后第二个单词 division 啊,除啊除法,然后第三个 ever 啊,那就是除零错误 啊,好,那这个错误呢?首先我说它和 exception 是 一样,它都是一个类,在代码的这个层面来说它是一个类,我们可以通过这个类来识别对向啊,所以你比如说看左边的代码儿, 如果说我们发现了说你输入的一个零,本来我想除以这个你输入的值,但是你输入的是零,那怎么办呢?哎,我们 不是用 exception, 因为 exception 说有一个错误太笼统了,我改一下,我改成 riz, 用这个 zero division error 这个类来实利化一个对象, 也就是这个具体的异常对象。好,那我把这个异常对象向外抛出,呃,那在 accept 这呢去捕获这个异常对象啊,那捕获这个异常对象,其实呢,只要是这个 zero division 这个这个 arrow 实际化的对象,它它意思大概意思就是你这个错误就是和除以零相关的这个错误。啊,是,是这么个意思啊,好, 那,呃当然,呃,我们这个是说我们自己可以 rad 十六万相关的这个错误啊,是,是这么个意思啊,好,那,呃当然,呃,我们这个是说我们自己可以 rad 十六万一场对象, 实际上呢,呃,我们自己很少手写,就实际化的一个对象抛,很多时候是我们写的代码本身 发生了除以零这样的一个错误,然后呢, python 在 执行到这行代码的时候,自动地触发,自动地替我们实际化一个对象,自动地替我们把它这个抛出去啊,所以你比如说啊,我在我这个 try 这代码,我就写一个七除以零, 当我们执行到这行代码的时候啊, python 执行这行代码一检查,哎,你怎么要除以零啊?哎,所以呢,他替我们实力划出来这个异常错误对象替我们跑出去啊,是这个样子啊,好, 所以呢,后边我会以这种实际代码呃为主去讲解,虽然我们可以睿字啥啥啥,但很多时候是我们即使不睿字,他只要发生类似代码错误就自动触发自动跑异常啊 啊,另外我再说一点,就是说,哎,那我下边 accept 这个后边 exception 能不能接收到?能不能捕获到这个异常对象呢?可以啊,呃,因为呢,就是说我 accept exception, 我 捕获这个异常,我是捕获由 exception 这个类 以及它的子孙类实体化出来的对象。那假使说我这个除零错误啊,这个 zero division error 这个错误,它是 exception 的 子类或者孙子类 啊,是符合要求的,所以这个 exception 是 可以符合到的啊,是这个细节我稍微说一下啊,好,这是第一个异常类,然后第二个异常类叫 file not found error, 啊,那还是这是四个单词啊啊? file 文件,然后 not 不 怎么怎么样,然后 found 是 找到, 那 file not found 是 文件没有找到这么一个错误啊,好,你你,你在这呢,当然我们也可以自己手动地去实列划出来这么一个对象,向外抛出, 但我们多数的时候,可能是我们写代码不小心,他就或者说不是代码的问题啊,你比如说我现在左边这个代码,我尝试对点点点这个文件读取它的内容,而实际上我当前这个电脑里边,当前这个目录下边根本就没有点点点这个文件。 哎,那这个时候 python 这个解释器执行到这行,哎,他发现没有这个文件呀,他们用这个,呃, python 就 会用这个类实体化出一个对象来,并且抛出去,哎,就是 python 解释器帮我们去干这件事了 啊,呃,所以这个也会抛出这个错误来啊。啊,那再来第三个,那就是 type arrow 啊,这个啊,那在这呢,我就不说我们自己去睿思了啊,那在实际编码当中,哎,我举个例子,比如说我编码当中我写了一个字母差, a、 b、 c、 d 加上一个数值一二三, 那这个时候呢?呃, a、 b、 c、 d 是 字母串,一二三是数值。我们这个加号在 python 当中可以连接两个字母串,也就是说你加号两边可以都是字母串,没问题,这个加号可以让两个数值相加啊,也就是说加号两边可以同时是数值, 但现在加号两边一边是字母串,一边是数值,这个类型它没法处理。所以啊,我们的这个 python 读取到这行,这行代码要执行,哎,他发现执行不了,所以他报错,抛出这么一个异常对象来,这个异常对象 它的类型就是 type arrow 啊,类型错误啊,这么个意思啊,好,再来 value arrow。 好, 那这个呢,我们再举个例子,比如说用户,我要求用户输入一个数值,然后呢,我针对数值进行一个数值转化,用 int 转换,但是用户在输入的时候,它输入的是啊,一二三, a、 b, c。 欸,那我用 int 就 会报错,因为 int 我 只能去处理括号形式的数值,你括号里边有 a、 b、 c, 我 处理不了,欸,那它就会抛出一个异常对象,或者说就叫报错啊,这个错误叫 value error 啊,好,再来叫 key, error, key 呢,就是字典里边那个 key。 欸,我们看代码, 假使说左边,我先定义一个空的字典,然后紧接着我去打印这个字典的 a 制 key, 我字典是空的,你根本就没有 h key 啊,你还要打印,所以呢,这个时候就会报错,报这个 key arrow 啊,说是报错,实际上呢,从代码的角度来说,它是报了一个异常错误对象 啊,是是是,这么个意思啊,好,那还有呢,就是 index arrow 啊,右边 index arrow 啊,对于代码来说,比如说我定义了一个 a 一 空列表, 那然后呢,我尝试访问这个空列表,缩写为零的元素,它是空的,所以它没有缩写为零的元素,那这个时候呢,也会报错啊,那这个报错呢,就是执行到这行代码的时候,我们的这个 python 解释器也说,哎, 这个列表是空的,根本就没有零缩写这个值,所以呢,它帮我们实际化出来这么一个错误对象,帮我们抛出,哎,就这么个意思啊, 好,当然还有很多其他的。呃,这个错误类啊,但是在这呢我就不说了啊,我们简单的了解一下就可以,这些呢是常见的,那接下来那我们要说什么呢?就是说既然有这么多不同种类的错误,那我如果用 accept exception 这个顶层的类去捕获这个异常,那捕获到了所有这些错误异常之后,我不知道它具体的到底是什么错误, 哎,所以呢,我没有办法有针对性的去处理,哎,这个就是痛点啊。也换换句话说,我们的需求是什么呢?我们的需求就是说我捕获到这个错场错误对象啊,异常对象,那我要做到的是具体的错误, 做具体的不同的处理。哎,你除零错误,我怎么怎么去处理?你文件找不到,我又怎么怎么去处理啊?是这么一个需求啊。好, 那接下来我们怎么来实现这个需求呢?啊?那也比较简单啊,实际上呢,我们可以写多个 accept 啊,比如说我在这再写一个 accept, 哎,那如果说 try 执行代码报了错误啊,然后呢?我补货异常,我先去判断一下 这个异常对象是不是由 zero division, error 这个类实力化出来的错误对象,如果是它实力化出来的对象,好,我拿过来补货到我去处理啊,那我去处理之后呢?呃, 多个 accept 啊,它就相当于那个 if else, if 那 个多分支结构,如果上边儿的 accept 符合要求,把这个异常对象补货到了,并且进行了处理,那么下边儿的这个 accept 就 不会处理,不会捕捉了啊。当然如果上边儿的这个没有补货到不符合要求, 假如说你,你在揣执行代码的时候抛了一个错误啊,一个异常对象,它是一个,比如说是一个文件未找到的一个错误, 哎,那你第一个 accept 不 符合要求,那就接着往下判断,那就会由这个最底下这个 exception 类捕获到啊,因为所有的错误其实都叫 exception 啊,所以 exception 作为最后的一个收底啊,可以这样啊,好,我们再举例啊,比如说我再添一个啊,那我判断一下,你发生错误了,你这个错误对象是什么类型啊?如果是文件未找到类型好,那我怎么怎么去处理? 就这样子啊,好,那我再写一个分支啊,那说你抛出了一个错误对象,我判断一下这个错误对象是不是 type error 这种类型啊,如果是这种类型,好,我作何去处理啊? 当然,我在这就不一一写了啊,我只不过是用现在这几个例子来说,我们 accept 可以 有一个分支的这么一个结构啊,它就实现了说不同的错误做不同的处理啊,就这么个需求啊, 好,那再接下来呢,我再说一下其他的这个语法啊,好,那其他的语法呢?我先把这个收一下,收一下之后呢?然后我们再介绍一个 else 啊,这个 else 是 什么意思呢?就是当我去 try 执行代码的时候,如果发生错误啊,那由 accept 来 捕获错误,处理错误,那如果不发生错误,那他就执行 else 啊,也就是说这个 accept 和 else 它们俩是互斥的啊,我踹下边的代码成功了,那就直接走 else, 不 成功报错了,那它就走 accept 啊,就这么个意思啊,当然,那针对于多 accept, 那 就是说再多 accept 是 一组,和 else 啊,是,是一个对立的,它们之间的互斥啊,好,然后再有一个是 finally 啊, 这个 final 类是什么意思呢? final 类是最终的意思啊,那就是当我们这个在 try 里边执行的代码,它有两种情况,要不然就是执行成功,一点毛病没有,要不然就是有错误发生。哎,这两种情况啊,有错误发生,那就由 accept 去捕获这个错误,然后进行处理, 没有错误发生,执行 else, 这是我刚才说的好,那么 finally 就是 说,不管你是成功了还是失败了,你成功了啊,那你走 else, 走完 else, 执行完 else 里边的代码,再执行 finally, 这是你成功的情况,如果你失败了,那你就走 accept 啊,执行 accept 里边的代码, 呃,当然你得捕获成功的情况下啊,你执行完 excel 的 代码,这是失败的处理吗?那最后你还得执行 finally, 哎,也就是说这个 finally 不 管你成功还是失败,你都要执行, 这个叫 finally 啊,就这么个意思啊,好啊,目前呢,我只能是说这个语法结构,这个只能说我们到一些稍微有点复杂的项目当中,才好说明它这个语法结构啊,我们暂时只能是了解一下这个语法结构就可以了啊, 好,那我快速的小结一下,那在这个视频当中呢,我讲的第一个就是错误类型啊,我们大概介绍了这一些常见的错误类型啊,然后呢,其实我们自己写代码的时候,我们当然可以通过睿字,然后呢,再通过这个类的名称去实际化一个对象,手动的去向外抛这个异常对象啊, 然后呢,其实我们在写代码的时候,很多时候是这个代码发生错误了啊,我们 python 执行到那行代码了,自动地替我们实力划这个对象,自动地替我们向外抛出啊,然后,呃,有很多个啊,那我针对这六个呢,给大家做了一个截图,我们简单看一下, 比如说,哎,现在这个截图左边我除以零了,那我执行这个 python 文件的时候,右边,哎,就爆了这么一个 zero division arrow, 这么一个错误啊,啊,那我们看第二个, 哎,那第二个呢?左边我尝试读取点点点这个文件的内容啊,右边呢,就报错了,没有这个文件啊,所以它下边写的是 file not found error 啊, 那后边呢?还有一个 error number 二,再后边啊,写的是 no such file or directory, 那 翻译过来就是没有这个文件或者目录啊,因为它它不知道你这个点点点到底是文件还是目录,但是呢,它找了没找到啊,是这么个意思啊,好, 然后我们再来啊,再来呢,呃,下一个,下一个就是类型错误,你看啊,我 a b, c, d 字母差加一百二十三,然后右边就报错了, type error 啊,这个意思啊,再继续, 然后在这个呢还是 int 一 二三 abc 啊,右边报错,报错呢,就是 value arrow 啊,这个类型啊,这个值错误啊,这叫值错误。哎,我们看右边叫报错信息,其实这个报错信息就是一个异常对象啊,或者说异常错误对象啊,只不过它打印出来就是这一大坨字啊, 再接着啊,接着呢,你看,我左边对一个空的字典访问它不存在的键,然后右边报错 key i 啊,然后后边还冒号 age, 你 尝试对 age 这个 key 去访问,但是没有,所以报错啊。 好,最后一个例子,那我们左边是一个空的列表,我却尝试访问这个列表的缩写为零的元素,所以右边报错, index arrow 啊,后边写的冒号,后边啊, list, index, 列表缩写,然后最后三个单词 out of range 是 超出了边界,超出了范围。 你比如说,那我这个列表假使说有十个元素,他的缩影就应该是零到九,哎,那这个时候我偏要打印这个列表缩影十个元素,但是他没有十,这个也叫超出范围啊, 好,再继续啊,这是最后一个,然后呢,我们第二点就是具体的错误处理, except 啊,如果说啊,我针对不同的错误不同的处理,就有这么一个语法啊,啊,第三个其他语法,那一个是 else, 就是 踹执行成功了,我执行代码,一个是 finally, 哎,不管成功还是失败,我都要执行的代码啊。 好,以上就是我这节视频所有的内容了啊,因为透彻,所以简单,我是讲师井水,这节视频呢,我们大概讲到的是蟒蛇书第一百七十六页啊,如果你有什么疑问或者你有自己的看法,欢迎在评论区留言啊,当然更呃,欢迎你关注我的这个账号,那么呢,让我们下个视频见。


很多人连 java 的 异常处理机制都搞不明白,那你写代码怎么可能不是一坨祥呢?为什么有这个视频啊?是因为今天我在部门里面做 code review, 我 发现呢,很多小伙伴在写代码时候呢,会把 exception 啊无脑往上抛,抛到 control 层, 最后呢,直接丢给局一场处理类来处理,把一些原生报错都直接反给前端了。可怕的是,我部门里面很多工作了七八年的老程序员都这么干,这种做法是对系统的极度不负责任,说白了就是完全没有搞清楚 java 里面的异常处理机制。那么我今天一个视频给你讲清楚 java 里面的异常处理机制到底该怎么玩。那么先问一个问题啊,为什么我们在写代码时候呢,调用有些方法,它会强制你显示的去处理异常,而有些方法它不用呢?这个呢,其实是 java 作者设置的一种 防御性编程的方式。对于这种必须要去处理的异常呢,有一个专用名词叫做受碱异常,它是在显示的,警告你啊,就是这个方法,因为外部环境的不确定性存在调用的风险,他强制要求你必须为这种潜在的风险制定容错方案。好 举一个最简单的例子啊,我们写一个除法的方法,入参呢,就两个值, a, b 分 别是被除数和除数啊,方法体呢,我们可以这么写, return a 除以 b。 那 如果你直接这么写的话,当 b 等于零的时候呢,程序会报错。 为了保证方法的健壮性,我希望呢,在用户传入 b 等于零的时候呢,强制提醒他注意这个问题。所以呢,我加了一行代码啊, e, f, b 等等,零 return exception 啊, 图数不能为零,就这么一行代码,它有什么用?它其实建立了一道前置的校验屏障,它强迫所有的代码方在编一阶段就必须审视这个边界条件,怎么审视?就是强制你显示的去处理这个异常。那我们都知道,面对异常,我们有两种处理方式,一种呢是无脑的往上去抛,另一种呢是 try catch 去处理异常。 什么时候用 try catch, 什么时候用 throw 呢?这个啊,取决于你这块代码,它的职责边界是什么,什么时候 try catch 啊?我举个例子啊,如果你正在写 control 层直面前端,其实你已经没有地方可以去抛一场了。底层报错了,你是决策者,你拥有完整的业务上下文,你可以决定 是给用户返回一个输入格式错误,还是兜底返回一个默认值。只要你能为结果负责,你就必须在此处捕获它,实现业务闭环。而决不应该是不管不顾还往上抛。最后呢,有大局异常处理来返回一个兜底的值, 那什么时候该 throw 呢?如果你正在携通用的 service, 你 根本就不知道上层是谁,你没有资格替上层做决定。这个时候呢,你的唯一职责就是保 保持信息的透明性,将异常的原封不动的透传出去,把决策权呢,交给拥有决策的调用者。就像我们前面讲的 control 层,他就是一个拥有决策的调用者。这样做有什么好处呢?使你的代码净位更加分明,职责更加清晰明了。再讲一个我们实际工作里面的例子,比如你 调用外部的一个 h t t p 接口,那大家都知道啊,使用 h t t p client 呢,会强制你去处理 time out of exception 啊,各种各样 exception 啊,很多人是不 会处理的,他直接在方法体上方直接就 throw 一个 exception 啊,把全部流程全都往上抛。那么用户如果在调用的时候呢,你给他返了一个 time out exception, 用户会很懵逼啊,他不知道你的代码内部到底发生了什么错误, 这个呢,对代码调用方式非常不友好的,所以呢,这个时候你最合适的方法是应该把这段去调用外部 h t t 接口呢,加上一个 try catch, 并且补获一个异常。然后呢,你可以专门定义一个调用外部接口异常的 exception, 里面的提示文字呢,是调用外部接口出现问题了, 把这个东西呢抛到前端去,那么这个时候,哪怕你在 control 层不处理,那么这个时候呢呢,也能够把正确的错误提示返给前端。 所以呢,从某种程度来讲,你处理异常的方法呢,就代表了你对程序的可控性到底有多强。最后呢,我再说一句啊,全局异常处理类呢,它是一个系统兜底方案,所有的异常呢,应该在 control 了层 识别完毕,并且清楚的处理,再明确提示给用户,这个呢,才是 java 异常处理最正确的方式。

拍三六十天,从零到精通第五十二天,一场捕获。哈喽,大家好呀,我是钱。 你有没有过这样的经历,辛辛苦苦写了一段代码,运行起来却突然啪的弹出一大串红色错误,程序直接退出。 比如,你让用户输入一个数字,结果他手一抖,输了个字母,或者你想打开一个文件,但文件根本不存在。 这时候程序不是提醒你错了,而是直接罢工,连后面的代码都不跑了。这在练习时还好,但如果这是你给朋友用的小工具,或者是一个网站后台,那可就太不友好了。 我们肯定希望程序能扛住意外,哪怕出错了,也能礼貌的说一句,你输错了,而不是直接崩溃。 isen 早就想到了这一点,所以提供了 try accept 机制,也就是一场捕获。你可以把它理解成先试着做一件事,如果出问题了,就走备用方案,而不是直接死掉。它的基本写法特别简单, try 缩进里面写可能出错的代码, except 后面跟错误类型缩进里面写代码出错时的处理方案。比如经典的例子就是除法不能除以零。 如果我们直接写十除以零, python 会立刻报错并终止程序。但用 try accept 就 不一样了, 在 try 里面我们写除法表达式, accept 里面我们写上错误提示。那现在程序不会崩溃,而是温柔地告诉你哪里不对,还能够继续往下执行后续的代码。 再举个更贴近生活的例子,假设你写了一个小助手,让用户输入年里你想情况下,用户会输入二十五这样的数字,但现实中,它可能会输字母二十五、 abc, 甚至直接回车。 如果你直接用 int 强制转换,一旦输入非数字,程序就炸了, 但加上异常处理,事情就稳了。现在不管用户输入什么程序都不会崩溃, 反而会友好地提醒他重新输入。你甚至可以加个循环,直到用户输对为止,但要记得加上 break, 当输入正确结束循环。而且, try accept 不 只是防崩溃这么简单, 它还能让你的代码逻辑更清晰。主流程只关心正常情况下该做什么,而各种万一都集中放在 accept 里处理。 就像开车时,你专注看路,安全气囊默默待命,平时感觉不到它,关键时刻却能救命。 更重要的是, python 的 每一种错误都有名字,比如 value、 error、 值不对、 index、 error、 列表越界等等。你可以针对不同错误写不同的应对策略,也可以用一个通用的 exception 来捕获所有错误。 不过一般建议具体一点,方便后续的代码调试。总之,学会使用 try accept, 你 的程序就能在出错时稳住不崩,给用户一个友好的回应,而不是直接报错退出。但当你开始构建更复杂的系统, 比如同时管理多个学生的信息,或者模拟一辆车的各种状态与行为,你会发现仅靠函数和变量越来越难以维持代码的清晰与可维护性。 这时候,面向对象编程的思想就显得尤为重要,它不是某种具体的语法技巧,而是一种组织代码理解问题的全新思维方式。下一期,我们就一起走进面向对象编程的核。


一场检测凭借其广泛的应用场景和相对简单的上手难度,成功跻身顶会发文热度榜前列,绝对是一个值得同学们关注的方向。但是就目前来看,一场检测领域方法论正快速引进和迭代,所以想入坑的同学们真的很有必要及时获取到最新前沿成果。 具体不管从算法改进、跨领域应用,还是解决数据不平衡等角度切入的创新思路,全都来自最新的 i c c v 二零二五。

开放零基础开始学第三章六点三,自定义异常捕获如何定义业务异常?对了,我已经把自己亲测有效的拍脏全套学习资料整理成了精简资料包,无偿分享,有需要的可以找我领取。 好,那自定义这个异常的话呢,我们要知道啊,自定义异常的这个用途,那主要呢就是利用异常的这个机制来编写这个程序的中断逻辑,那编写的时候呢,咱们必须得继承现有的异常,再增加额外的功能。 好,那边咱们看啊,主要我把它划成了三个部分。那第一个的话,我们说了,你要写自定义异常,那一定是说我的 程序逻辑是希望他能够什么通过 try accept 的 这种方式进行中断的。那这边比如说我出现了错误,我想让用户继续往下执行,那其实用这个异常是不合适的。 那第二个的话呢,那咱们去编写的自定义异常定是不能从头去写的,他必须继承我们现有的异常,可以继承自 exception, 也可以继承自我们的其他的异常。 那继承完之后的话呢,那这一边主要继承了之后呢,是想要给现有的异常增加额外的这个功能啊,这是它的主要用途。 那异常怎么去继承,怎么去编辑呢?你看一下我的这个例子啊,那这边当我想要去, 呃,使用一个自己定义的这个异常叫 my exception, 那 我可以直接去继承 exception, 那这样的话呢,这个 my exception 就 变成了一个异常了,那这时候的话,这个 my exception 你 可以进行补货,那这边除了补货之外,你还可以什么?哎,这个去抛出这个异常,是吧?啊,那这样我就产生这样的特定异常,把它抛出啊,那边补货,那补货 except, 加上这个异常。 好,怎么抛出,怎么补货呢?那其实如果你需要自己抛出异常的话,我们使用的是这个叫做 race。 啊,抛出异常,那怎么来补货呢? accept, 我 就可以进行补货。 啊,那这个其实就是什么呢?这个 my exception 啊,其实就是我自己定义的一个异常信息。好呢,可以来看看,来去定义一个自己需要的异常。 好,那这里边的话,我们先仿照我们的这个 ppt 啊,写一个叫做 my 啊 exception。 好, 那它在这里呢?继承我们啊。啊, exception。 好,这样我们留一个空啊,什么都不写,一会儿我们再去 follow。 那 在这里我们如果产生这个异常啊,会是啥情况呢?咱们可以 raise my exception。 好,咱们看这是不是就产生了一个异常啊?但是产生的这个异常的名称叫什么呢?叫 my exception。 在 哪哈产生呢?就在我们的第一行。好,产生的这个异常的原因啊,就叫做 my exception。 好, 既然它有这个原因,我们是不是就可以捕获它呀?所以呢,咱们可以用 try。 好, 那 raise my 啊 exception, 那 咱们给它补货。 好,我捕获成 exception, 然后咱们输出这个 e。 好, 那捕获的时候呢?我发现什么?哎,这里边没有捕获啊,那这边是因为什么?我们这个异常其实什么都没做,是吧?好,所以呢,咱们在里边捕获的时候啊,我们把它改成什么呢?改成我们的 my exception。 好,这边我们发现啊,确实发出这个异常,捕获异常了,但是呢,因为什么都没有做,所以呢你输出的这个 e 呀,他的结果也是空的,看到了吧? 啊?那人不管用 exception 还是 my exception, 其实我们都没有办法发现捕获到的这个东西,我们给他去输出,所以呢,这时候我们怎么办呢?咱们要回到我们的这个最开始这个异常上,我们要给他什么呢?做点事情是吧?咱们来丰富他, 好,怎么来丰富它呢?那这边大家可以看一下,我们一般的异常会怎么产生呢?比如说像这个值错误,是吧? 那叫 value arrow。 好, 然后 value arrow 这后边的参数呢?咱们来去运行啊。哎, 好,你看他是可以直接运行的,那在这里呢,我们给他抛出这个异常, 咱们来看看。好,那抛出来之后的话呢,咱们看看,这就是产生了一种异常了,是吧?这个异常叫做值错误,那值错误的话呢,对应后边的这个参数啊,这些参数就会显示到值错误的这后边。 哎,这什么呢?这是当你去遇到这个 v 六 i, 这是系统定义的一个异常的时候,我们会这样去显示,那咱们在这里面定义的异常,其实我也想要实现这个功能,那这边怎么做呢?请你可以参考他来去重新编写我们的这个自己的这个异常,是吧?好,那咋做呢? class 啊,那咱们这个叫什么呢?咱们不叫 value arrow, 叫做 name arrow 啊,就当我的名字为什么的时候,我这时候就让它进行报错,是吧?那这个 name arrow 的 话呢?我们如果想要使用 value arrow 的 形式,你可以直接去继承它, 但是呢,遵照习惯,一般的情况下,我们直接去继承谁啊?继承我们的 exception。 好,那再一遍的话,大家要记得我们的 solo 的 原则其中有一条是什么,当我们如果能够成功调用子类的时候,那他的副类也一定能够成功使用,是吧?这是满足我们的 solo 的 原则。 好,所以呢,咱们来去验证我们系统写的这个程序有没有符合我们的这个原则,是吧?啊,那在里边习惯啊,我们要继承这个 excel。 好,那继承 exception 的 时候呢,我们说了,这个像 value io 一 样,我要读入一个参数,咱们要显示这个参数,是吧?哦,所以呢,我在这边 define iit, 是 吧? 初步函数,那它的第一个参数呢?叫 self。 好, 第二个呢?我们接收进来的啊,咱们叫啥?叫做 message 吧, 接收点消息进来啊,接收点消息进来之后呢,我们来去用 self 点 message, 等于啊 message。 好, 我这边去接收这个消息,然后呢,让他进行一个赋值是吧? 好,然后接下来话呢,我们说了,咱们得让这个东西进行一个输出,对吧?咱们看补货了之后,我再去输出这个 e, 咱们要让它进行输出,所以呢,怎么办呢?我们在这边再去把这个东西给它输出出去,是吧?好,输出出去的时候呢,我们其实不想直接把这个属性暴露给别人。 哎,不想别人直接去用这个 message 怎么办呢?咱们是不是可以把给它封装成一个函数啊?好,那这边 d f 啊,那这边我们就叫做 m s g 啊,叫做这样的一个函数。好,这个函数用来做什么呢?那这边它是用来返回的好一点。什么东西呢?我们返回一个 f strength 啊,名字不允许使用哪个呢? self 点 message, 那 在这里它的属性哎,我这边就这个花括号给它括起来,让它在 f strings 里边进行一个解析。 好,那别人再去调用这个 name arrow 的 这个,我调用这个函数了,是吧?觉得调用起来不方便,我希望呢,用它的时候就像用属性一样,是吧?好,那所以呢,我给它加一个属性的装饰器, 好 property。 那 这样的话呢,我们 message 虽然它写起来是函数啊,返回的时候是啊,一个 f string 是 吧?但是我这边调用它的时候呢,是可以直接把它当做属性来去调用的啊。 好,那这回的话呢,咱们就可以来去判断了,是吧?然后那这边当我们这个名字是谁呢啊?咱们看是用汤姆还是用杰瑞吧来。好,那这边 try。 哎,我这边, 呃揣的时候呢,咱们在上面给他使用一个啊,名字是吧?好,名字等于啊杰瑞。好,这样有一个变量,是吧?那如果我们的这个名字和我们的杰瑞要相等了 啊,这时候我就需要去捕获它了,是吧?然后呢,这种情况下我们就抛出谁呢?我们就抛出一个叫做 name arrow 的 这个异常。 那 name arrow 的 这个异常的时候抛出来之后呢,我们希望什么呢?把我们的这个 name 给它传进去啊,那这样的话呢,我们就抛出了一个带参数的这个异常了,是吧?哦,那捕获的时候我们可以怎么捕获呢?我也可以捕获一个 name arrow, 是 吧?然后这边把它叫什么?叫做 n e, 嗯,之前叫 e 是 吧?我这回改了,改叫 n e。 好, 输出的时候呢,咱们知道这个地方有个 message 属性是吧?所以我就直接输入 n e 点 啊, m s g。 好, 虽然它是函数,但是我用装饰器把它改了是吧?改成属性了,所以我在输出的时候也可以是属性。 好,那这回的话呢,我们就可以看一下,那当你的名字是杰瑞的时候,那我这边就会抛出这个异常,那这边如果不是就不抛出是吧?那咱们先换回 tom 来去正常执行一下,好,没有问题是吧?什么都不显示,那这回我给它改成杰瑞 啊,你看这边显示了啊,你不能叫做杰瑞,为啥呢?因为当他是杰瑞的时候,我在捕获异常的这个语句块当中就把这个名字读进去了,判断相等,那这时候我就抛出一个我自己定义的一个异常,这个异常名字叫做内麦 iro 啊,你看本来他的逻辑是没有问题的是吧?也没有语法错误,但这就是我定义的业务上的一个异常啊。那抛出的时候呢,我们这边不但是抛出了这个异常,而且把抛出异常的这个原因有这个名字我放进去。 好,放进去之后,那这边我们的这个 name arrow 这个类啊,其实是可以啊,继承 exception 的, 所以呢,它可以作为我们的异常去抛出。那这边接收的信息呢?作为 message 参数,并且复制给我们的实力化的 self message, 那 复制给我们的这个 self message, 当它捕获这个 name 这个异常的时候呢,我把这个 name arrow 啊,给它命名为 n e, 那这边它其中就有一个用函数通过装饰器变成了一个属性 m s, g, 是 吧?啊?那这边我们就返回了啊,这样的一串信息啊,那这边你看这个就是我们去自己定义的一个异常,那这边它其实 比较有用的什么呢?其实就是我可以把函数变成一个属性来去直接使用。 ok, 咱们看一下这样的一个例子。 好,那回来这个是什么呢?是我们怎么来去自己定义这个异常,是吧?咱们可以通过 race 来去抛出,然后 accept, 再去把这个东西再去接住, 是吧?那抛出的时候咱们说可以带参数啊,那这个参数其实就是 my accept 啊,继承字 exception, 然后通过 i i t 参数,那这边通过我们的类里边的这个方法对它进行处理,处理完之后呢,让它进行输出,好输出的时候呢?我们这边相当于把它实化 好,实力化的话我们可以带属性带方法,对吧?你看这边就是把我们的整个的逻辑用异常处理的这个方式给它中断,我们用其他形式去处理了。 那其实我们有的时候再去用的时候,发现在系统当中也带了类似的这个用法,那他其实会更简单,这叫啥?叫做位子语句,那咱们记得 open 打开文件是吧?好,打开的时候我们可能会遇到各种各样的这个错误,比如说打开文件的时候文件路径不对 啊,文件名称不对,文件不存在,打开时候文件权限不对等等,这一系列的这个操作其实都会涉及到什么?打开的时候什么时候关闭? 好,所以这里我们引入一个位子语句,在打开的时候如果出现问题,那在里面只要离开了位子语句,我们就自动关闭掉,是吧?比如说打开的时候出现异常,那这边离开了位子语句,我就自动关闭掉啊,那这边当你打开文件时候,这个, 呃,我们的这个文件名错误,那,那这边也是可以做这个事情的,那我们说如果你想要去实现这个位子语句的话,我们也可以拿我们自定义的这个类来实现。 好,那他实现的这个方式是什么呢?是这样的那位子语句啊,其实主要使用了双下划线 enter 和双下划线 exit 这样的两个方法 啊,那这边咱们又想起了什么?鸭子类型是吧?就是说他长得像鸭子啊,走路像鸭子,或者叫起来像鸭子,我就认为他是鸭子。好,那这边比如说我们定一个叫做 my class 啊,那这边当我们使用位子语句这个对象,只要被调用,那这边我们就执行这个 enter 啊,这个方法里边的这个所有的这些语句,是吧?那这边之后的话, at 后边的话呢,会把我们的这个类给进行一个实体化, 那这边当你去定义什么呢?这个类里边的 exit 这样的一个方法的时候,就是离开了位子一块这部分就会自动执行了, 那这边当你定义好了这个 my class 之后,那咱们就可以使用什么 with my class, as mc, 对 吧?然后呢去使用实力化的这些方法,那这边当你去调用这句的时候,它就自动执行了 enter, 那当你离开了这个位子的这个语句块的时候,它就自动执行了双下巴 c exit 啊,那这个就是什么?就是我们的位子语句和我们怎么来去自己定义的这个类啊,去进行一个结合。比如说我们像现在打开文件是不是使用位子啊? 那那这个除了这个呢,我们还能想到什么使用位子呢?打开网页是吧?然后位子,然后打开一个网页,读取网页里边的内容。好,那咱们使用这样的这个位子,然后 s max 啊,这样的一个方法,就可以去实现我们自定义一类的一个位子的用法了。 好了,最后呢我来给你去总结一下,这个关于自定义常,必须要让它 去继承你现有的异常,不能是直接继承 object 啊,因为在我们的这个 exception 啊,这些异常里边会有提前编辑好的异常处理的这个逻辑啊,这部分我们必须要继承 啊,那这边我们去继承的时候呢,你可以从这个 exception 继承,也可以从其他的这个子类继承,但是我们会发现什么从子类和从 exception 继承呢?就是结果是一样的,是吧?那因为我们都要重新编写异常的这个逻辑,所以呢在这边还是推荐大家使用 exception。 那 另一个的话呢,我说编辑好自己的异常,怎么来引发异常呢?咱们要使用 race 这样的一个关键字可以引发异常,那补货的时候呢,也可以补货我们当前的这个异常, 那捕获了之后的话呢,我们可以通过 as 这个关键字把你的异常啊实力化,并且调用你的自定义异常里边的这些属性和方法。 那同时的话呢,还为大家去讲解了关于 with 这个语句它的一个用法,那这边和我们的这个异常处理一样,它是可以呢去通过我们的 enter 啊这个魔术方法去进入到我们的这个位子的语块当中,然后通过 exit 来去离开语块进行一个自动执行了。好,那以上呢就是我们怎么来去使用自定义异常来去处理我们系统当中这些问题。