异常捕获与生成器
异常捕获理论
1.什么是异常
在我们程序员的眼里异常就是我们经常说的bug,我们在运行这个程序的时候因为某些因素的影响下,非正常
结束了这段代码的运行,就是我们理解的bug
2.异常是什么
def func():
pass
outer():
"""
File "D:/pythonProject/day21/课堂练习01.py", line 3 # 错误地址,行数
outer(): # 错位行为
^ # 表明错误行为
SyntaxError: invalid syntax #左边是错误类型(语法错误),右边则是说为什么错误(该语法未定义)
"""
就像上面的报错其实就是异常错误,我们常见的报错形式,语法错误是最不能容忍的一种错误方式,因为脑子
里没东西了我才用这个我们可以点击错误位置取寻找是哪里发生错误,而最后一行则是我们更改这个错误的关
键,左边类型错误右边的错误原因根据这个我们就可以解决百分之九十的错误。
3.错误的类型
TypeError:类型错误,对象用来表示值的类型非预期类型时发生错误
AttributeError:属性错误,特性引用和复制失败时会引发的错误
NameError:试图访问的变量名不存在
SyntaxError:语法错误,代码形式错误
KeyError:在读取字典中k值不存在就会出发这个错误
IndexError:索引错误,使用的索引不存在或超出可索引范围
IndentationError:缩进错误
TabError:tab和空格混合使用产生的错误
4.异常可以背分为两大类:
语法错误:在书写代码的时候语法不规范的话才会触发语法错误,当我们遇到语法错误的话就应该直接改正不能
让他存在,它存在就证明你不是很专业
逻辑错误:逻辑错误就是我怕们书写的代码都符合规范但是逻辑上这个程序走不通或者报错那么就属于逻辑错误,
逻辑错误的话可以被容忍,但是该改还得改,令人头秃的一大因素
代码写出来必须自己先进行测试,否则被测试发现嘿嘿,不是很妙哦!!!
![image](https://img2022.cnblogs.com/blog/2904194/202207/2904194-20220712190130887-187813315.png)
异常捕获实操
1.为什么需要进行异常捕获
当我们在不知道什么时候会发生错误时或在我们感觉这个地方可以会报错时那么我们就可以采用异常捕获的方法
来规避掉这些报错,在规避的同时预测吗他为什么会报错并将要是他报错了的话,将解决办法也丢给他让他不会
报错,这样就可以直接规避并解决这个报错行为
2.捕获措施
try: # 尝试关键字
可能会出现错误的代码
except 上方可能会报错的代码的报错类型 as e: # except尝试预测报错方法如果真的错误了就是用这
个后面的例外方案,跟上报错类型如果预测失败的话那么就会直接报错而不会运行运行之后的代码,except可
进行连 环使用,跟上as后面跟上一个报错提示,可以不需要这一步这一步只是为了方便我们查询报错,跟上默
认一般e来接收报错
print(如果判断成功打印出这个错误看一下)
解决这个报错的plan B直接解决
try:
可能会出错误代码
except TypeError as e:
对应解决方案
3.万能捕获
try:
可以出错的所有方案
except Exception as e: # 解决上方报错的万能预测方案一
print(e)
解决方案
except BaseException as e: # 解决上方报错的万能预测方案二和上方一样是父子俩
print(e)
解决方案
4.可以与捕获联系的内置方法
4.1 else否则老朋友了,哪里都有它吐了,不过这次只有在上方尝试没有报错的情况下他才会执行,如
果报错他也不执行,看到这个还是蛮爽的
try:
可能会出错误代码
except TypeError as e:
对应解决方案
else:
只有在上方执行美哟报错的情况下才会执行else
4.2 finally最后,这个就比较豪横了,无论上方代码有没有错误都会执行这大哥和这大哥后方的东西
try:
可能会出错误代码
except TypeError as e:
对应解决方案
else:
只有在上方执行美哟报错的情况下才会执行else
finally:
无论怎么报错我都执行就是这么的豪横
4.3 isinstance可以使用这个预测上方是什么数据类型不对的话就会直接报错,而对的话才会继续往下执行
代码
name = 'jsoeph'
isinstance(name, bool)如果预测正确继续往下运行,不正确来吧直接进入主题报错
根据上方预测成功的类型继续操作
4.4 raise主动报错,堪称无敌自己和自己玩,唉就是报错
name = input('请输入您的姓名>>>:')
if name == 'Alice':
raise Exception(‘只要是输入了Alice,进了我这道门那么你就死都别想出去,嘿嘿嘿’)
else:
我只要Alice别人绕道走就行
![](https://img2022.cnblogs.com/blog/2904194/202207/2904194-20220712191132946-1001659019.png)
异常捕获实战
1. for循环的内部结构
l1 = [11, 22, 33, 44, 55, 66, 77, 88, 99] # 首先自建一个列表
res = l1.__iter__() # 将列表的可迭代对象转为迭代器对象,在for循环中会将in后面的可迭代对象直接转为迭
代器对象
while True: # 额最普通的循环
try: # 尝试,监控下方代码
print(res.__next__()) # 打印这个已经被转为迭代器对象的结果使用__next__依次取出通过while
except Exception as e: # 报错就截胡,管他什么先截胡再说
print(e) # 自己加的没想到打印不出来
break # 上方循环完报错完被截胡后强制中止while循环
![image](https://img2022.cnblogs.com/blog/2904194/202207/2904194-20220712190234374-1693480222.png)
生成器对象
1.生成器的本质
生成器的本质其实就是迭代器,只是为了节省代码和内存空间就是用生成器来代替,生成器所拿到的数据会像
转变为一个地址,当我们第一次调用这个函数的时候这个函数不会立即执行只有当他事先运行过一次的时候才
会给你出一个值。使用关键字yield来定义生成器
2.生成器的作用
生成器其实就是为了我们节省代码行数和内存空间
3.生成器实践
def func():
print('明月几时有?把酒问青天,不知天上宫阙。''今夕是何年,我欲乘风归去,又恐琼楼玉宇。')
yield '返回值1'
print('高处不胜寒,起舞弄清影,何似在人间。''转朱阁,低绮户,照无眠''不应有恨,何事长向别时圆。')
yield '返回值2'
print('人要有悲欢离合,月有阴晴圆缺,此事古难全,但愿人长久,千里共婵娟。')
yield '返回值3'
"""
其实一个yield就是一个生成器了,只是兴致来了我次啊使用三个生成器叠加,yield可以多次调用,yield
后面跟的值也是可以返回的,跟什么返回什么就像我们之前使用的return返回值,yield就是生成器的返回值
关键字,多个数值的话可以使用逗号隔开
"""
print(func) # 先调用一次上方的函数并不会被执行
res = func() # 将上方函数赋值给res
print(res.__next__()) # 调用你res生成器然年后他会给你返回一个值,然后直接停止代码
# 明月几时有?把酒问青天,不知天上宫阙。今夕是何年,我欲乘风归去,又恐琼楼玉宇。
# 返回值1
print(res.__next__()) # 当你再次调用的时候才会给你返回第二这数据值
# 高处不胜寒,起舞弄清影,何似在人间。转朱阁,低绮户,照无眠不应有恨,何事长向别时圆。
# 返回值2
print(res.__next__()) # 第三次调用返回第三次的数据值
# 人要有悲欢离合,月有阴晴圆缺,此事古难全,但愿人长久,千里共婵娟。
# 返回值3
![image](https://img2022.cnblogs.com/blog/2904194/202207/2904194-20220712190343514-1893535436.png)
yield用法
1.yield也可以接收值
def func(name, shop=None):
print(f'{name}今天我们去哪里玩呢?')
while True:
shop = yield
print(f'{name}{shop}欢迎您的光临')
res = func('joseph')
res.__next__()
res.send('足疗店')
res.send('高级会所')
res.send('洗浴中心')
2. send和next()都是让生成器向下走一次
3. send可以给上一个yield的位置传递值, 不能给后一个yield发送值. 在第一次执行生
成器代码的时候不能使用send()
![image](https://img2022.cnblogs.com/blog/2904194/202207/2904194-20220712190504180-301644461.png)
生成器表达式
1.生成器表达式
l1 = [i**2 for i in range(10) if i > 3] # 列表生成式
print(type(l1)) # <class 'list'>
print(l1) # [16, 25, 36, 49, 64, 81]
res = (i**2 for i in range(10) if i > 3) # 生成器生成式
print(type(res)) # <class 'generator'>
print(res) # <generator object <genexpr> at 0x00000293035AB970>
print(res.__next__()) # 16
print(res.__next__()) # 25
print(res.__next__()) # 36
print(res.__next__()) # 49
print(res.__next__()) # 64
print(res.__next__()) # 81
![image](https://img2022.cnblogs.com/blog/2904194/202207/2904194-20220712190607527-338860324.png)