异常情况报错、抽象类

一、异常

1、错误

  • 语法错误
  • 逻辑错误

2、异常

程序执行过程中出现问题导致程序无法执行

3、常见异常

AttributeError        试图访问一个对象没有的属性,比如foo.x,但是foo没有属性x
IOError               输入/输出异常;基本上是无法打开文件
ImportError           无法引入模块或包;基本上是路径问题或名称错误
IndentationError      语法错误(的子类) ;代码没有正确对齐
IndexError            下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError              试图访问字典里不存在的键
KeyboardInterrupt      Ctrl+C被按下
NameError             尝试访问一个没有申明的变量
SyntaxError           Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError             传入对象类型与要求的不符合
UnboundLocalError     试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它
ValueError            传入一个调用者不期望的值,即使值的类型是正确的

BaseException          所有异常的基类
SystemExit             解释器请求退出
KeyboardInterrupt      用户中断执行(通常是输入^C)
Exception              常规错误的基类
StopIteration           迭代器没有更多的值
GeneratorExit          生成器(generator)发生异常来通知退出
StandardError          所有的内建标准异常的基类
ArithmeticError        所有数值计算错误的基类
FloatingPointError     浮点计算错误
OverflowError          数值运算超出最大限制
ZeroDivisionError      除(或取模)零 (所有数据类型)
AssertionError         断言语句失败
AttributeError         对象没有这个属性
EOFError               没有内建输入,到达EOF 标记
EnvironmentError       操作系统错误的基类
IOError                输入/输出操作失败
OSError                操作系统错误
WindowsError           系统调用失败
ImportError            导入模块/对象失败
LookupError            无效数据查询的基类
IndexError             序列中没有此索引(index)
KeyError               映射中没有这个键
MemoryError            内存溢出错误(对于Python 解释器不是致命的)
NameError              未声明/初始化对象 (没有属性)
UnboundLocalError      访问未初始化的本地变量
ReferenceError         弱引用(Weak reference)试图访问已经垃圾回收了的对象
RuntimeError           一般的运行时错误
NotImplementedError    尚未实现的方法
SyntaxError             Python 语法错误
IndentationError        缩进错误
TabError                Tab 和空格混用
SystemError            一般的解释器系统错误
TypeError               对类型无效的操作
ValueError              传入无效的参数
UnicodeError             Unicode 相关的错误 
UnicodeDecodeError       Unicode 解码时的错误
UnicodeEncodeError       Unicode 编码时错误
UnicodeTranslateError    Unicode 转换时错误
Warning                  警告的基类
DeprecationWarning      关于被弃用的特征的警告
FutureWarning           关于构造将来语义会有改变的警告
OverflowWarning         旧的关于自动提升为长整型(long)的警告
PendingDeprecationWarning    关于特性将会被废弃的警告
RuntimeWarning         可疑的运行时行为(runtime behavior)的警告
SyntaxWarning          可疑的语法的警告
UserWarning            用户代码生成的警告

4,异常处理

语法格式一:【这个格式 用的比较多一些】

try:
    可能发生异常的代码(1/0except[Exception [as err]]:
    异常处理1

语法格式二:

try:
   可能引发异常现象的代码
except:(可以没有)
   出现异常现象的处理代码
finally: (finally里面的代码必须要执行)
   try代码块结束后运行的代码

语法格式三:

try:     (必选)
   可能引发异常现象的代码
except:  (必选:二选一)
   出现异常现象的处理代码
else:    (可选)
   未出现异常现象的处理代码
finally:  (必选:二选一)
   try代码块结束后运行的代码
try:
    demo = 123
    print(demo)
except:
    print('出现了异常')
else:
    print('没有出现异常')
finally:
    print('我一定要执行')

在这里插入图片描述

try:
    demo = 'hello python'
    print(demo)
    print(demo.index('a'))
    d = 1//0
except NameError:    # 指明了这部分只用来处理NameError引发的异常,虽然精确了,捕获范围变小了
    print('demo没有被定义')
except ValueError:   # 成功捕获到ValueError的错误
    print('该字符并不处于字符串当中')
except Exception:    # Exception里面包含所有的精确异常 放在最后
    print('未知的错误')

Exception是上面所有Error类的父类

错误别名的写法:

try:
    print(a)
except NameError as demo:
    print('具体的异常描述信息是:%s'% demo)

在这里插入图片描述

5,自定义异常

  raise
a=1
b=0
if b==0:
    raise ZeroDivisionError('integer division or modulo by zero')

在这里插入图片描述

a=1
b=0
if b == 0:
    raise ZeroDivisionError('不能这样做')

在这里插入图片描述
制造异常就是通过 raise 来制造异常

案例:
异常时可以避免的,不可避免的异常,比如 用户输入信息,网络原因登录不上

# 个人开发思维

name='小范'
age = 22
def check_name(name):
    if name.find('范')>=0:
        print('名字里含有范这个字')

def check_age(age):
    if age>=20:
        print('这个人年龄大于等于20岁')

check_name(name)
check_age(age)
# 企业级的开发思维是这样:

name='小范'
age = 22
def check_name(name):
    if name.find('范')>=0:
        raise NameError('名字里含有范这个字')

def check_age(age):
    if age>=20:
        raise ValueError('这个人年龄大于等于20岁')
try:
    check_name(name)
    check_age(age)
except NameError:
    print('名字里含有范这个字...处理完毕。。。')
except ValueError:
    print('这个人年龄大于等于20岁...处理完毕。。。')

上面的报错使用的是原生异常,如果我们把原生异常在开发的过程中使用到了的话,那么其它地方再用就用不了了,所以我们使用自定义异常

那么,自定义异常如何去使用,就涉及到一个 “类” 的概念

自定义异常的条件:

  • 必须是一个类
  • 要被 Exception所包含,Exception必须要是自定义异常类的父类

自定义异常类的语法格式:

    class 自定义异常类名(Exception):
         pass

主动触发异常现象
    raise 异常类对象

例:

class NameIsError(Exception):  # 代表Exception是NameIsError的父类  
    pass

class AgeIsError(Exception):
    pass  # pass就是占位的作用,不会让程序报错,你所有的东西都是父类给你的

6、异常的处理机制

# 层层嵌套甩锅
try:
    def demo():
        d = 1//0

    def demo1():
       try: 
          demo()
       except NameError:
           print('sisi帮助你')

    def demo2():
        demo1()

    try:
        demo2()
    except NameError:
        print('波波帮助你')
except ZeroDivisionError:
    print('0不可以做分母')

在这里插入图片描述

用户登录信息校验案例

要求:用户输入用户名,密码后对信息进行校验:
1、用户名长度在3-8个字符
2、用户名中只能出现英文字母和数字
3、密码长度必须是6位
4、密码必须由纯数字组成

思考:
1、用户名、密码如何得到?
2、各种规则如何使用异常处理机制实现?

# 自定义异常类
class NameIsError(Exception):
    pass
class PwdIsError(Exception):
    pass

    # 输入得到 用户名和密码
name = input('请输入用户名:')
pwd = input('请输入密码:')

    # 监测 是否符合规范 复用性很强 >> 那就用函数
# 符合四个规范就登录成功,只要一个不满足条件,就进行处理
def check(name,pwd):
    """检查用户名和密码是否符合规范"""
    if  len(name)<3 or len(name)>8:  # 用户名长度在3-8个字符
        raise NameIsError('用户名长度不在3-8个字符之间')
    if not name.isalnum(): # 用户名中只能出现英文字母和数字
        raise NameIsError('用户名中只能出现英文字母和数字')
    if len(pwd) != 6: # 密码长度必须是6位
        raise PwdIsError('密码长度必须是6位')
    if not pwd.isnumeric():  # 密码必须是纯数字组成
        raise PwdIsError('密码必须是纯数字组成')
    print('登录成功')

check(name,pwd)

在这里插入图片描述
在这里插入图片描述

用提示异常的方式写!!!

# 自定义异常
class NameIsError(Exception):
    pass
class PwdIsError(Exception):
    pass

    # 输入得到 用户名和密码
name = input('请输入用户名:')
pwd = input('请输入密码:')

    # 监测 是否符合规范 复用性很强 >> 那就用函数
# 符合四个规范就登录成功,只要一个不满足条件,就进行处理
def check(name,pwd):
    """检查用户名和密码是否符合规范"""
    if  len(name)<3 or len(name)>8:  # 用户名长度在3-8个字符
        raise NameIsError('用户名长度不在3-8个字符之间')
    if not name.isalnum(): # 用户名中只能出现英文字母和数字
        raise NameIsError('用户名中只能出现英文字母和数字')
    if len(pwd) != 6: # 密码长度必须是6位
        raise PwdIsError('密码长度必须是6位')
    if not pwd.isnumeric():  # 密码必须是纯数字组成
        raise PwdIsError('密码必须是纯数字组成')
    print('登录成功')
try:
    check(name,pwd)

except NameIsError as e: # 精确捕获异常处理的意义;前面函数抛出异常没有关系,在这里进行拦截打印异常
    print(e)
except PwdIsError as p:
    print(p)

在这里插入图片描述



二、抽象类

1.抽象类:
当父类中部分方法不能满足所有子类或大多数子类需求时,父类再写这个方法就没有太大意义了,
但父类强制子类必须有该方法时,在父类中定义成抽象方法

像这样的,,父类——animal类的吃的方法是吃饭,子类——cat类吃的方法是吃鱼,运行的时候,运行的也是子类方法,再定义一个子类——dog类,吃的方法吃狗粮,那和父类吃的方法又不一样,,所以父类写个吃饭的方法没有意义
在这里插入图片描述
这时候,用一个模块 abc

 import abc
    class animal(metaclass=abc.ABCMeta):    # 这个类还要继承 abc.ABCMeta===>这个是一个抽象的类,继承它就能用了
   
       @abc.abstractmethod  #定义一个抽象方法,注意!强制子类中必须有哪些方法,子类必须用到这个方法,这个时候必须定义抽象类
       def eat(self):
         pass              # 具体的方法实现步骤没有,直接用pass,定义成抽象方法
       def sleep(self):       #这个方法是普通方法
        print("睡觉")
    
    class cat(animal):
       def eat(self):
        print("吃猫粮")
        
    c = cat()
    c.eat()
    c.sleep()

在这里插入图片描述
上图中,“吃猫粮”调用的子类eat的方法;“睡觉”调用的父类sleep的方法;
同时也说明,父类定义的普通类(sleep()),也是可以调用的

定义抽象方法需要的两点情形:

1.父类的方法不能满足大多数子类需求
2.还得强制子类必须得使用该方法

这个时候咱们在父类中把这个方法定义成 抽象的

抽象类的特质:

1)抽象类:可以有抽象方法  也可以有普通方法
2)抽象类:不能直接实例化(创建对象),必须通过子类间接实例化
3)抽象类:抽象类里面允许有构造函数

验证:能不能有构造方法?

  import abc   #第三方模块
   class animal(metaclass=abc.ABCMeta):
       def __init__(self,name):     # 构造函数(父类中有了构造方法带参的,下面子类中也要有)。传参!==> 名字name
         self.name = name
    
      @abc.abstractmethod
       def eat(self):
        pass
      
       def sleep(self):   #普通类!
        print("睡觉")
   
   class cat(animal):
    def __init__(self,name):
    super().__init__(name)
    def eat(self):
      print("吃猫粮")

   c = cat("小红")
   c.eat()
   c.sleep()

在这里插入图片描述
构造子类对象时,传一个猫的名字;创建子类对象,子类对象调用子类构造函数,子类构造函数调用父类构造函数,调用父类构造函数,父类也创建了一个对象
但是,若直接创建看行不行,如下:
在这里插入图片描述
TyprError: 不能实例化抽象类animal(带有抽象方法的)
说明:抽象类不能直接实例化(实例化就是创建对象),必须通过子类间接实例化

接口:都是抽象方法的类

其实接口就是一个普通的类,只不过说里面所有的方法咱们认为它没有任何的实现,父类没有强制子类必须继承,所以说这是接口的一个特点

假如说,父类里面所有的方法都不能满足子类需求,里面全是抽象方法,而且不强制子类必须使用,这个时候就可以用接口
总之,抽象类是子类必须使用父类中的抽象方法,而接口在这里不强制子类

 class animal():
      def eat(self):
        pass
      def sleep(self):
        pass

 class cat(animal):
      def eat(self):
        print("吃鱼")
      def sleep(self):
        print("睡觉")
    
    a = cat()
    a.eat()
    a.sleep()

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值