异常捕获
什么是异常
异常是程序运行时导致错误的bug,会导致程序运行终止。
例如在pycharm中,程序报错会输出一段跟错误相关的报告,并标出出错类型和错误代码位置。
异常的类型
NameError | 变量名不存在,调用的名字没有被定义 |
IndexError | 索引值超出范围,索引值超过列表最大长度触发 |
KeyError | 键不存在,当在字典中读取对象时输入不存在的键触发 |
SyntaxError | 符号错误,在代码区使用中文符号等无法识别的字符时触发 |
TypeError | 数据类型错误,输入了不符合类型的字符 |
异常的类别
语法错误
if True
name
语法层面的错误不允许出现,程序会直接报错
逻辑错误
逻辑错误一般是赋值、输出时写了错误的对象名,导致运行的结果与预期出现差别,程序会允许逻辑错误,但程序员需要检查出来。
异常捕获
当不确定代码是否会出错,或者代码出现错误的位置时,可以使用异常捕获来辅助解决bug。
异常捕获格式
try:
可能出错的代码 #代码不会真的执行,只用于模拟监控
except 错误类型1 as e:
出现错误1之后执行的代码
except 错误类型2 as e:
出现错误2之后执行的代码
except 错误类型3 as e:
出现错误3之后执行的代码
......
try下面写的代码只会判断是否出错,根据出错类型执行对应的代码。
错误类型写入内容为NameError等异常的名称,也可以输入万用错误类型。
except Exception as e: # 万能错误类型1
print(e)
except BaseException as e: # 万能错误类型2
print(e)
异常捕获的其他操作
1.else和finally
except Exception as e:
print('程序出现错误')
else:
print('程序没有错误')
finally:
print('监测结束')
else是当程序没有错误时执行对应的子代码
finally是监测部分结束之后执行的代码,无论是否报错都会进行
if......else | 除了以上条件外的其他情况下才执行 |
for/while......else | 当循环按照设置好的条件下结束才执行 |
try......else | 当监测程序没有错误时才执行 |
2.assert()
断言,功能是判断目标的数据类型是否一致,如果和判断的数据类型不一样直接报错
name = 'jason'
assert isinstance(name, list) #变量name的数据类型不是list,直接报错
3.raise()
raise的作用是直接报错,执行时直接生成一段自定义的错误报告
raise Exception('生成一段错误报告')
异常监测在使用时会占据额外的内存,监测的代码部分能简短就简短点。
生成器对象
生成器对象本质就是自定义迭代器对象,使用自定义迭代器可以帮助我们优化代码结构,使代码看上去更加简洁。
关键字yield
yield关键字的作用是,当它出现在函数代码中时,首次调用函数时会把函数本身转换成迭代器对象,不会执行函数其他代码。
def index():
print('一段函数代码')
yield
res = index()
print(res)
此时打印res得到的结果不是函数index,会显示如下
<generator object index at 0x0000024BAD685BF8>
generator的意思是生成器,经过yield之后函数本身被转换成了一个生成器,也就是自定义迭代器,此时就可以使用__next__来调用迭代器。
yield的特殊功能
用yield中断代码
def index():
print('一段函数代码')
yield
res = index()
res.__next__()
res.__next__()
连续两次调用自定义迭代器,会显示报错
这是因为yield有特殊功能,就是每一个yeild都会在它当前那一行代码停止,相当于把代码截成多个部分,每个yeild截一部分,每次调用迭代器从对应的yeild执行到下一yeild,而如果yeild下面没有代码,此时调用就会报错。
def index():
print('一段函数代码')
yield
print('另一段代码')
yield
print('第三段代码')
yield
res = index()
res.__next__()
res.__next__()
res.__next__()
此时就能分段执行函数的三个部分
如果yeild后面有数值或者变量名,也会像return一样返回到函数外。
用yeild接收信息
def index(name,food=None):
print(f'{name}准备干午饭!!!')
while True:
food = yield
print(f'{name}正在吃{food}')
res = index('jack')
res.__next__()
首次执行函数index时,会在food = yeild处停止,无论yeild在哪个位置,都会执行中断的功能。
def index(name,food=None):
print(f'{name}准备干午饭!!!')
while True:
food = yield
print(f'{name}正在吃{food}')
res = index('jack')
res.__next__()
res.send('米饭')
res.send('面条')
res.send('炸鸡')
此时最后会按顺序输出jack正在吃XX,因为send()的功能是往迭代器中传值,并自动执行__next__的功能启动迭代器。
生成器表达式
生成器表达式的作用就是使用自定义迭代器快速生成自己需要的功能,用于节约代码。
l1 = [i**2 for i in range(10) if i > 3]
print(l1)
该代码的效果为,变量i从范围0到10循环+1,当i>3时,输出i的二次方并输入到列表l1中。
生成器的作用就是压缩代码空间,并且像函数一样,在需要的时候调用。