一、异常捕获
1.什么是异常捕获
异常捕获就是程序在运行过程中出现了异常会导致程序提前结束运行 异常就是日常人们所说的 ‘bug’
2.异常的结构
Tracebool(most recent call last):
File"E:/PycharmProjects/pythonProject1/111.py", line 17
age
NameError: name 'age' is not defined
① 关键字line所在那一行
精准提示你哪一行代码出错
② 最后一行冒号左侧
是错误的类型
③ 最后一行冒号右侧
是错误的具体原因(也是bug的关键)
3.异常的类型
NameError
IndexError
KeyError
SyntaxError
TypeError
4.异常的分类
a.语法错误
不允许出现的,一旦出现请立刻修改!!!
b.逻辑错误
允许出现的 允许出错之后修改即可!!
ps:写代码先自己大概测一遍,然后再提交!!!
二、异常捕获实参演练
1.什么时候才可能会需要自己写代码处理异常
当代码不确定什么时候会报错的情况下
eg:编写网络爬虫访问网址数据并处理 有可能会出现断网数据没有处理
2.异常捕获的使用相当于是提前预测可能出现的问题并提前给出处理的措施
3、异常捕获的代码实现
3.1.基本语法结构(针对性很强)
try:
可能会出错的代码(被try监控)
except 错误类型1 as e:
对应错误类型1的解决措施
except 错误类型2 as e:
对应错误类型2的解决措施
except 错误类型3 as e:
对应错误类型3的解决措施
except 错误类型4 as e:
对应错误类型4的解决措施
3.2.万能异常(笼统的处理方式)
try:
name
d={'name':'ella'}
d['pwd']
123+'hello'
except Exception as e:
print(e)
except BaseException as e:
print(e)
4.异常铺货其他操作补充
4.1.else与finally
try:
name
expect Exception as e:
print('你出错了,请检查后再试')
else:
print('try监测的代码没有出错的情况下正常运行结束 则会执行else子代码')
finally:
print('try监测的代码无论有没有出错 最后都会执行finally子代码')
4.2断言
name = 'ella' # 通过一系列的手段获取来的数据
assert isinstance(name, list) # 断言数据属于什么类型 如果不对则直接报错 对则正常执行下面的代码
print('针对name数据使用列表相关的操作')
4.3.主动抛异常
name = input('username>>>:').strip()
if name == 'jason':
# raise NameError('jason来了 快跑!!!')
raise Exception('反正就是不能过')
else:
print('不是jason 那没事了')
5.强调
1.异常捕获能尽量少用就尽量少用
2.被try监测的代码能尽量少就尽量少
三、异常捕获练习
1.for循环内部的本质
# 需求:使用while+异常捕获实现for循环功能
l1 = [11, 22, 33, 44, 55, 66, 77, 88, 99]
res = l1.__iter__()
while True:
try:
print(res.__next__())
except Exception as e:
break
2.实际项目的错误展示
1.先看具体的报错信息
2.再看具体的定位信息(由上往下看)
3.尽量将错误缩小到某个具体的变量
4.注意力就关注在出现这个变量的代码身上即可
四、生成器对象
1.本质其实就是迭代器对象
只不过迭代器是解释器提供给我们的(现成的)
生成器是我们自己定义出来的(自己动手)
__iter__和__next__
2.学习生成器对象的目的是为了优化代码
一种不依赖于索引取值的通用方式
可以节省数据类型的内存占用空间(主要)
3.生成器对象代码实现
def index():
print('我是谁呀 嘿嘿嘿~')
yield 111, 222, 333
print('你追我 如果你追到我 我就... 嘿嘿嘿~')
yield 222
print('实在跑不动了 嘿嘿嘿~')
yield 333
当函数体代码中有yield关键字 那么函数名第一次加括号调用不会执行函数体代码 而是由普通的函数变成了迭代器对象(生成器) 返回值
print(index) # <function index at 0x000001F499F7A5E0>
# res = index()
print(res) # <generator object index at 0x0000021E18BACA50>
res.__next__()
res.__next__()
res.__next__()
yield可以在函数体代码中出现多次
每次调用__next__方法都会从上往下执行直到遇到yield代码停留在此处
print(res.__next__())
print(res.__next__())
print(res.__next__())
print(res.__next__())
yield后面如果有数据值 则会像return一样返回出去
如果有多个数据值逗号隔开 那么也会自动组织成元组返回
五、生成器对象
def index():
print('我是谁呀 嘿嘿嘿~')
yield 111, 222, 333
print('你追我 如果你追到我 我就... 嘿嘿嘿~')
yield 222
print('实在跑不动了 嘿嘿嘿~')
yield 333
当函数体代码中有yield关键字
那么函数名第一次加括号调用不会执行函数体代码
而是由普通的函数变成了迭代器对象(生成器) 返回值
print(index) # <function index at 0x000001F499F7A5E0>
res = index()
print(res) # <generator object index at 0x0000021E18BACA50>
res.__next__()
res.__next__()
res.__next__()
yield可以在函数体代码中出现多次 每次调用__next__方法都会从上往下执行直到遇到yield代码停留在此处
print(res.__next__())
print(res.__next__())
print(res.__next__())
print(res.__next__())
yield后面如果有数据值 则会像return一样返回出去
如果有多个数据值逗号隔开 那么也会自动组织成元组返回
六、生成器对象
def index():
print('我是谁呀 嘿嘿嘿~')
yield 111, 222, 333
print('你追我 如果你追到我 我就... 嘿嘿嘿~')
yield 222
print('实在跑不动了 嘿嘿嘿~')
yield 333
当函数体代码中有yield关键字
那么函数名第一次加括号调用不会执行函数体代码
而是由普通的函数变成了迭代器对象(生成器) 返回值
print(index) # <function index at 0x000001F499F7A5E0>
res = index()
print(res) # <generator object index at 0x0000021E18BACA50>
res.__next__()
res.__next__()
res.__next__()
yield可以在函数体代码中出现多次
每次调用__next__方法都会从上往下执行直到遇到yield代码停留在此处
print(res.__next__())
print(res.__next__())
print(res.__next__())
print(res.__next__())
yield后面如果有数据值 则会像return一样返回出去
如果有多个数据值逗号隔开 那么也会自动组织成元组返回
课堂练习
编写生成器 实现range方法的功能
def my_range(start,end=None,step=1):
if step<1:
step=1
if not end:
end=start
start=0
while start<end:
yield start
start+=step
for i in my_range(0,13,3):
print(i)
七、yield其他用法
def index(name,food=None):
print(f '{name}准备干午饭!!!')
while True:
food = yield
print(f'{name}正在吃{food}')
res = index('jason')
res.__next__()
res.send('生蚝') # 传值并自动调用__next__方法
res.send('韭菜') # 传值并自动调用__next__方法
res.send('腰子') # 传值并自动调用__next__方法
八、生成器表达式
l1 = [i**2 for i in range(10) if i > 3]
print(l1)
l1 = (i**2 for i in range(10) if i > 3)
print(l1) # <generator object <genexpr> at 0x000001A793439C10>
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] False
B. res=[11,12,13,14] False
C. res=[20,21,22,23] True
D. res=[21,22,23,24] False
ps:掌握技巧即可 无需深究 纯粹为了考试而出 没有多少实际意义 嵌套不符合编程规范