今日内容
异常常见内容
1.BaseException
这个异常类型就是所有异常的基类,在自定义异常类是也需要去继承这个类,当使用作为异常捕获的类型时就会自动捕获所有异常
2.IOError
该异常类型的意思就是在文件IO流传输出现问题就会捕获到的异常 一般来说打开文件或者读写文件都有可能引发这种异常类型
3.KeyError
在python中看到key关键字就可以知道这个异常类型是由字典所引发的,他的意思就是在访问字典中不存在的键会捕获异常
4.TypeError
这个是最常见最容易引发的异常类型,在对象比较或者执行表达式的时候,只要对象数据类型和需求对不上就会引发这个异常类型
5.OverflowError
在python中无论整数还是浮点数,他们能够参与的数学计算值都是有长度上线的,当结果或者数字长度超出数据类型规定值就会引发OverflowError类型的异常
6.NameError
这个异常类型被引发的原因就在于访问了当前程序中不存在的变量name指代的就是变量名
7.IndentationError
没使用正确缩进时引发的异常( 语法错误(的子类) ;代码没有正确对齐)
8.SyntaxError
Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
9.IndexError
下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
异常处理语法结构
基本语法结构
try:
待监测的代码
except 错误类型:
针对上述错误类型定制方案
-
try except结构
概念:
try except结构在python异常处理结构中使用得最为频繁,其中try子句中的代码为可能引发异常的语句,except语句捕获相应的异常。 也可为理解为,#当try子句代码执行异常并且被except子句捕获事,执行except子句语块
代码举例:
mathScore = input('英语成绩:')
try:
mathScore = int(mathScore)
if(mathScore>=0 and mathScore<=100):
print("输入的英语成绩为:",mathScore)
else:
print("输入的不在本科成绩范围内")
except Exception as e: # e是系统提示的错误信息
print('输入错误')
# 偷个懒用Exception万能异常 针对常见的错误类型统一处理
-
try except else结构
概念:
如果try代码子代码中出现了异常且改异常被except捕获,则可以执行相应的异常处理代码,此时就不会执行else中的子代码
# 如果try中的代码没有抛出异常,则继续执行else子句
#语法结构:
try:
待监测的代码(可能会出错的代码)
except Exception as e: # e就是系统提示的错误信息
针对各种常见的错误类型全部统一处理
else:
try的子代码正常运行结束没有任何的报错后 再执行 else子代码
#代码举例:
wprt = input('英语成绩:')
try:
wprt = int(wprt)
except Exception as e:
print('输入的数值有误!')
else:
if (wprt >= 0 and wprt <= 100):
print("输入的英语成绩为:", wprt)
else:
print("输入的不在本科成绩范围内")
#假设输入的不是1-100就会执行e,如果输入的是1-100那么说明没有任何报错将执行else
-
try except else finally结构
在try...except...finally结构中,如论try子句是否正常执行,finally子句中的代码总会得到执行!
q = int(input('q:'))
e = int(input('e:'))
try:
c = q/e
print(c)
except Exception:
print('e不能为o')
finally:
print('运算结束')
# 无论try是否正常执行 finally肯定会执行
异常处理补充
1.断言
什么是断言?其实assert断言就是用于判断一个表达式,在表达式条件为 false 的时候触发断言异常,断言可以在条件不满足程序运行的情况下直接返回错误,而不必等待程序运行后出现崩溃的情况
name = 'jason'
# assert isinstance(name, int)
assert isinstance(name, str) # 设置断言肯定name是字符串
print('哈哈哈 我就说吧 肯定是字符串')
name.strip()
2.主动抛异常
异常捕获后为什么还要主动去抛出一个异常呢?这是为了方便我们知道出现异常的具体情况,我们还可以自定义异常
name = 'jason'
if name == 'jason':
raise Exception('老子不干了')
## 捕获后运行不会报错,再抛出就会看到异常
else:
print('正常走')
异常处理实战应用
1.异常处理能少用就少用
2.被try监测的代码尽量少
3.当代码中出现无法控制的情况报错才考虑使用
4.使用while循环+异常处理+迭代器对象 完成for循环迭代取值的功能
l1 = [11, 22, 33, 44, 55, 66, 77, 88, 99]
# 1.先将列表调用__iter__转变成迭代器对象
iter_l1 = l1.__iter__()
# 2.while循环让迭代器对象反复执行__next__
while True:
try:
print(iter_l1.__next__())
except StopIteration as e:
break
生成器对象
1.本质
内置有__iter__和___next__的迭代器对象
2.区别
迭代器对象是解释器自动提供的
数据类型\文件对象>>>:迭代器对象
生成器对象是程序员编写出来的
代码、关键字>>>:迭代器对象(生成器)
3.创建生成器的基本语法
函数体代码中填写yield关键字
def my_iter():
print('哈哈哈 椰子汁很好喝')
yield # 关键字
4.函数体代码如果有关键字yield那么函数名加括号不会执行函数体代码,# 会形成一个生成器对象(迭代器对象)
5.使用加括号之后的结果调用__next__才会执行函数体代码
#res.__next__()
6.每次执行完__next__代码都会停在yield位置 下次基于该位置继续往下找第二个yield
def my_iter(): # 1
print('哈哈哈 椰子汁很好喝') # 4.执行之后返回第二个next
yield 111, 222, 333
print('呵呵呵 从小喝到大')
yield 111, 222, 333
print('嘿嘿嘿 特种兵牌还可以')
yield 111, 222, 333
print('哼哼哼 千万别整多了 倒沫子 头发掉光光')
yield 111, 222, 333
res = my_iter() # 2.变成生成器不执行函数体代码
r1 = res.__next__() # 3.执行__next__之后
print(r1)
r2 = res.__next__() # 5.已经是生成器所以执行next不执行函数体代码
print(r2)
r3 = res.__next__()
print(r3)
r4 = res.__next__()
print(r4)
'''yield有点类似于return 可以返回返回值'''
yield冷门用法
def eat(name, food=None):
print(f'{name}准备用餐')
while True:
food = yield
print(f'{name}正在吃{food}')
res = eat('jason')
res.__next__()
# res.send('汉堡') # 1.将括号内的数据传给yield前面的变量名 2.再自动调用__next__
# res.send('包子')
# res.send('面条')
生成器表达式
说白了就是生成器的简化写法
# l1 = [i ** 2 for i in range(100)]
# print(l1)
l1 = (i ** 2 for i in range(100)) # 生成器对象
print(l1) # <generator object <genexpr> at 0x000001DFC07F7E40>
for i in l1:
print(i)
"""
面试题(有难度)
大致知道流程即可
"""
def add(n, i): # 普通函数 返回两个数的和 求和函数
return n + i
def test(): # 生成器
for i in range(4):
yield i
g = test() # 激活生成器
for n in [1, 10]:
g = (add(n, i) for i in g)
"""
第一次for循环
g = (add(n, i) for i in g)
第二次for循环
g = (add(10, i) for i in (add(10, i) for i in g))
"""
res = list(g)
print(res)
#A. res=[10,11,12,13]
#B. res=[11,12,13,14]
#C. res=[20,21,22,23]
#D. res=[21,22,23,24]
'''大致知道起始数即可'''