一、异常捕获
1.错误类型
语法错误>>>syntaxerror
名字错误>>>namerror
索引错误>>>Indexerror
缩进错误>>>indentationerror
等等......
2.异常处理语法结构
1.语法结构
try:
可能报错的代码
except 错误类型:
针对上述错误制定的方案
时刻监视,一旦报错,就会拿着报错行去比except行,如果错误类型对的上,就按一开始设置的法子绕过不报错,如果对不上还是会报错
2.查看错误的信息
try:
可能报错的代码
except 错误类型 as x: # 拿一个变量接收一下
针对上述错误制定的方案
print(x) # 可以把报错那个描述单独拎出来,不影响程序中止
3.再多留几手针对不同的错误类型
try:
可能报错的代码
except 错误类型1 as a:
针对上述错误制定的方案
except 错误类型2 as a:
针对上述错误制定的方案
except 错误类型3 as a:
针对上述错误制定的方案
______________________________
但是注意,如果自上而下,只要报错,就会去下面的预留里找,找到一个类型符合的就不再找其他可能报错的代码了
4.万能异常
Exception
try:
可能报错的代码
except Exception as a:
针对上述错误制定的方案
try:
name
except Exception as x:
print(x)
>>>
name 'name' is not defined
5.与else连用
当try的子代码都没有错误,就走else的子代码
6.与finall连用
不管try的子代码有没有错误,最后都执行finally子代码
3.异常处理补充
1.断言(可能会在底层代码看到)>>>assert
用于判断一个表达式,在表达式条件为 false 的时候触发异常
预言一个条件,如果符合就往下走,不符合就报错预言错误
assert xxxxxx
2.主动抛异常 ***重要
重要性:
某些情况下,需要反馈消息给更上层的调用者,告诉它有一些异常情况发生
语法结构:
raise Exception('不玩了!') # 主动报错
↑
(上面这个错误类型可以自行设置,也可以用万能报错)
try:
username = input('请输入用户名>>>:').strip()
if username != 'jason':
raise Exception('未授权的用户名')
password = input('请输入密码>>>:').strip()
if password != '666':
raise Exception('密码错误')
except Exception as e:
print(e)
4.实战应用
1.前提:
能少用就少用——监测会占用资源
被try监测的代码,越少越好,影响效率
课堂小题目:
l1 = [11, 22, 33, 44, 55, 66, 77, 88, 99]
运用while循环+迭代器对象+异常捕获 模拟for循环的原理
try:
res = l1.__iter__()
while True:
print(res.__next__())
except Exception as e:
pass
二、生成器对象
1.本质
本质还是自带__iter__ __next__用法的迭代器对象
2.区别
生成器对象是自己创的,迭代器
3.用法
函数体代码内,写一个关键字yield,就变成生成器对象,可以逐步取值
一个函数内一旦存在yield,调用函数时不会直接执行函数体代码
yield可以用于返回值,但不同于return,函数一旦遇到return就结束了
了,而yield可以保存函数的运行状态挂起函数,用来返回多次值
def my_iter():
print('嘿嘿')
yield 111
print('哈哈哈')
yield 222
print('嗨害嗨')
yield 333
————————————————————
my_iter() # 如果这样调,不好意思,没反应,因为已经变生成器了 ————————————————————
res = my_iter()
# 生成器就是迭代器
r1 = res.__next__()
print(r1)
r2 = res.__next__()
print(r2)
r3 = res.__next__()
print(r3)
# 函数体代码中如果有这个关键字,那么函数名+()不会执行函数体代码,而是变成一个生成器对象
# 拿一个变量名来接收生成器(迭代器对象)
# res = my_iter()
# 使用加括号之后的结果调用__next__才会执行函数体代码
# 每次执行完__next__后会停在yield位置,下次基于这个位置继续往下找yield
# yield有点类似return
# 后面可以设置返回数据
# 再拿一个变量名来接受yield的返回数据
>>>
嘿嘿
111
哈哈哈
222
嗨害嗨
333
课堂中习题:
自定义生成器,对标range功能 # range 本身就是一个迭代器
def my_range(start, stop=None, step=1):
if not stop: # 意味只传了一个数
stop = start # 指向一下
start = 0
while start < stop: # 就相当于只要比预期值小就一直循环返回小的值,然后加一次步长
yield start
start += step
————————————————————————————————————
res = my_range(10) # 等于 res = my_range(0,10,1)
for i in res:
print(i)
4.yield冷门用法(接受传参)
-
拓展send()
>>>传值 # 将括号内的数据传给yield 前面的变量名,再自动调用
__next—
def func(name):
food_list = []
print('大哥%s准备吃东西了...' % name)
while True:
# x拿到的是yield接收到的值
# x = ['一杆枪', '两枚C4']
x = yield food_list # x = ['一杆枪', '两枚C4']
print('大哥%s抽了 %s' % (name, x))
food_list.append(x)
t = func('jack')
res = t.send(None) # 等同于next(g),先完成初始化
print(res)
t.send(['一杆枪', '两枚C4']) # 不能传2个值,会报错,但是列表算一个值
print(res)
——————————
# 如果不想传参了,用close()关闭
t.close()
三、生成器表达式
本质就是生成器的简化写法,生成器代码只有调用的时候才执行
res = ( i for i in [1,2,3,4,5,6] if i != 2)
# 不用他列表的值永远产生不出来,不用就是摆设
面试题
for n in [1,10] # 注意,就两个值,不调就肯定不运行,但是运行肯定以n=10收尾,所以n必等于10
标签:__,python,res,生成器,yield,day16,报错,print
From: https://www.cnblogs.com/wznn125ml/p/16799710.html