python基础21-异常捕获-生成器
今日学习
异常捕获
异常捕获实参演练
异常捕获练习
生成器对象
yield其他用法
生成器表达式
异常捕获
经典疑问?
1.怎么理解异常?
程序在运行的过程中如果出现了异常会导致整个程序的结束?
异常就是程序员口中的‘bug’
2.什么时候需要自己写代码处理异常
当代码不确定什么时候会报错,拿不准的情况下
比如编写网络爬虫访问网址数据并处理,有可能会出现断网数据没有处理不了.
-
异常的结构
Traceback (most recent call last):
File "D:/pythonProject/day21/02 异常的结构.py", line 13, in <module>
name
NameError: name 'name' is not defined
1.关键字line所在行
精准提示你哪一行代码出错
2.最后一行冒号左侧
是错误的类型
3.最后一行冒号右侧
错误的具体原因(也是改bug的关键)
-
异常的类型
NameError #访问的变量名不存在
IndexError #索引错误,索引不存在,常为索引超出序列范围
KeyError #使用了映射中不存在的关键字时引发的关键字错误
SyntaxError #语法错误
TypeError #类型错误
-
异常的分类
切记!!
1.语法错误
不允许出现的,一旦出现请立即修改!!
2.逻辑错误
允许出现,允许出错之后修改即可!!
写代码一定要自己大致的看一下,然后再提交
-
异常捕获实参演练
-
异常捕获的使用相当于提前预测可能出现的问题,并提前给处理的措施
-
基本语法结构()
try: 可能会出错的代码(被try监控) except 错误类型1 as e: # e就是具体错误的原因 对应错误类型1的解决措施 except 错误类型2 as e: # e就是具体错误的原因 对应错误类型2的解决措施 except 错误类型3 as e: # e就是具体错误的原因 对应错误类型3的解决措施
-
万能异常(笼统的处理方式)
try: # name # d = {'name':'jason'} #d['pwd'] 123 + 'hello' except Exception as e: # 万能异常方式1 print(e) except BaseException as e: # 万能异常方式2 print(e) ----执行结果--------------- unsupported operand type(s) for +: 'int' and 'str'
-
异常捕获其他操作补充
4.1.else与finally #没有异常执行else,finally出现的话,有没有异常最终都要执行。
try:
name
except Exception as e:
print('你出错了 你个小垃圾')
else:
print('try监测的代码没有出错的情况下正常运行结束 则会执行else子代码')
finally:
print('try监测的代码无论有没有出错 最后都会执行finally子代码')
------执行结果-------------
你出错了 你个小垃圾
try监测的代码无论有没有出错 最后都会执行finally子代码
---------------------------------------------------------------
断言 #assert
name = 'jason' # 通过一系列的手段获取来的数据
assert isinstance(name, list) # 断言数据属于什么类型 如果不对则直接报错 对则正常执行下面的代码
print('针对name数据使用列表相关的操作')
---------------------------------------------------------------
主动抛异常 #rais
name = input('username>>>:').strip()
if name == 'jason':
# raise NameError('jason来了 快跑!!!')
raise Exception('反正就是不能过')
else:
print('不是jason 那没事了')
-------------------------------------------------------------------
5.强调
1.异常捕获能尽量少用就尽量少用
2.被try监测的代码能尽量少就尽量少
-
异常捕获练习
#for循环内部的本质 #需求:使用while+异常捕获实现for循环的功能 l1 = [11, 22, 33, 44, 55, 66, 77, 88] while True: try: print(res.__next__()) except Exception as e: break ----------------------------------------------------------------
生成器对象
-
1.什么是生成器对象?
本质是迭代器对象,只不过迭代器是解释器提供我们的(现成的)
生成器是我们自己定义出来的(自己动手,丰衣足食)
双下iter 和双下next
-
2,我们学生成器的目的是什么?
为了优化代码
一种不依赖于索引取值的通用方式
可以节省数据类型的内存占用空间()
-
3.生成器对象代码实现
def index():
print('我是谁呀 嘿嘿嘿~')
yield 111, 222, 333
print('你追我 如果你追到我 我就... 嘿嘿嘿~')
yield 222
print('实在跑不动了 嘿嘿嘿~')
yield 333
print(index)
print(res)
res = index()
res.__next__() #yield可以在函数代码中
res.__next__()
res.__next__()
print(res.__next__())
--------------执行结果--------------
<function index at 0x0000018C9E738280>
<generator object index at 0x000001B754CAAC10>
我是谁呀 嘿嘿嘿~
你追我 如果你追到我 我就... 嘿嘿嘿~
实在跑不动了 嘿嘿嘿~
------------------------------------
解释
----------------------------- -
"""
当函数体代码中有yield关键字
那么函数名第一次加括号调用不会执行函数体代码
而是由普通的函数变成了迭代器对象(生成器) 返回值
"""
yield可以在函数体代码中出现多次
每次调用__next__方法都会从上往下执行直到遇到yield代码停留在此处
还是同样的例子
def index():
print('我是谁呀 嘿嘿嘿~')
yield 111, 222, 333
print('你追我 如果你追到我 我就... 嘿嘿嘿~')
yield 222
print('实在跑不动了 嘿嘿嘿~')
yield 333
print(index)
print(res)
print(res.__next__())
#print(res.__next__())
# print(res.__next__())
# print(res.__next__())
---------执行结果-------------------
我是谁呀 嘿嘿嘿~
(111, 222, 333)
"""
yield后面如果有数据值 则会像return一样返回出去
如果有多个数据值逗号隔开 那么也会自动组织成元组返回
"""
-
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__方法 -----------执行结果------------- jason准备干午饭!!! jason正在吃生蚝 jason正在吃韭菜 jason正在吃腰子
生成器表达式
# 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)
-----------------执行结果------------------------
[16, 25, 36, 49, 64, 81]
<generator object <genexpr> at 0x000001C7566F6900>
---------------解释---------------------------
相比列表表达式,将[]换成了(),返回对象不是一个列表,而是一个生成器,相比列表更加省内存
(返回值 for 元素 in 可迭代对象 if 条件)