异常捕获
1.如何理解异常
程序在运行的过程中如果出现了异常会导致整个程序的结束
异常就是程序员口中的'bug'
2.异常的结构
Traceback (most recent call last):
File "D:/pythonProject/day21/课堂练习.py", line 1, in <module>
name
NameError: name 'name' is not defined
1.关键字line所在行
精准提示你哪一行代码出错
2.最后一行冒号左侧
是错误的类型
3.最后一行冒号右侧
错误的具体原因(也是修改bug的关键)
3.异常的类型
NameError
IndexError
KeyError
SyntaxError
TypeError
4.异常的分类
1.语法错误
不允许出现的 一旦出现请立即修改!!!
2.逻辑错误
可以出现的 出错之后修改即可
ps:写代码先自己大致运行一遍 然后再提交
异常捕获实操演练
1.什么时候才可能会需要自己写代码处理异常
当代码不确定什么时候会报错的情况下
eg:编写网络爬虫访问网址数据并处理 有可能会出现断网数据没有处理不了
2.异常捕获的使用相当于是提前预测可能出现的问题并提前给出处理的措施
3.异常捕获的代码实现
3.1 基本语法结构(针对性很强)
try:
可能会出错的代码(被try监控)
except 错误类型1 as e: # e就是具体错误的原因
对应错误类型1的解决措施
except 错误类型2 as e: # e就是具体错误的原因
对应错误类型2的解决措施
except 错误类型3 as e: # e就是具体错误的原因
对应错误类型3的解决措施
except 错误类型4 as e: # e就是具体错误的原因
3.2万能异常(笼统的处理方式)
try:
name
d = {'name':'curry'}
d['pwd']
123 + 'hello'
except Exception as e: # 万能异常方式1
print(e)
except BaseException as e: # 万能异常方式2
print(e)
4.异能捕获其他操作补充
4.1 else与finally
try:
name
except Exception as e:
print('抱歉 你出错了')
else:
print('try监测的代码没有出错的情况下正常运行结束 则会执行else子代码')
finally:
print('try监测的代码无论有没有出错 最后都会执行finally子代码')
4.2 断言
name = 'curry' # 通过一系列的手段获取来的数据
assert isinstance(name,list) # 断言数据属于什么类型 如果不对则直接报错 对则正常执行下面的代码
print('针对name数据使用列表相关的操作')
4.3 主动抛出异常
name = input('username>>>:').strip()
if name == 'curry':
raise NameError('curry来了')
raise Exception('反正就是不能过')
else:
print('抱歉 那不是curry'
5.强调
1.异常捕获能尽量少用就尽量少用
2.被try监测的代码能尽量少就尽量少
异常捕获练习
1.for循环内部的本质
#需求:使用while+异常捕获实现for循环的功能
l1 = [11,22,33,44,55,66,77,88]
res = l1.__iter__()
while True:
try:
print(res.__next__())
except Exception as e:
break
'''
1.先看具体的报错信息
2.再看具体的定位信息
由下往上查看
3.尽量将错误缩小到某个具体的变量
4.注意力就关注在出现这个变量的代码身上即可
'''
user_data = {
'1': {'name': 'jason', 'pwd': '123', 'access': ['1', '2', '3']},
'2': {'name': 'kevin', 'pwd': '321', 'access': ['1', '2']},
'3': {'name': 'oscar', 'pwd': '222', 'access': ['1']}
}
# 8 定义全局变量
is_login = {
'is_login':False,
'access_list':[]
}
def login_auth(func_id):
def outer(func):
def inner(*args,**kwargs):
# 10 先判断用户是否为登录状态
if is_login.get('is_login'):
# 11 获取当前用户执行权
access = is_login.get('access')
# 12 判断当前函数编号是否在用户权限内
if func_id in access:
res = func(*args,**kwargs)
return res
else:
print('你当前没有编号为%s的函数执行权'%func_id)
else:
# 1.获取用户编号
user_id = input('请输入用户编号>>>').strip()
# 2.判断用户编号是否存在
if user_id in user_data:
# 3.获取用户名和密码
username = input('请输入用户名>>>').strip()
pwd = input('请输入密码>>>').strip()
# 4.比对信息
real_dict = user_data.get(user_id)
if username == real_dict.get('name') and pwd == real_dict.get('pwd'):
# 5 获取权限
access = real_dict.get('accesss')
# 9 数据正确的情况下,更改全局质量
is_login['is_login'] = True
is_login['access_list'] = access
# 6判断当前用户是否含有当前被装饰函数的执行权限,假设当前被转送给hi函数的红能编号func_id
if func_id in access:
# 7有权限
res = func(*args,**kwargs)
return res
else:
print('你没有当前功能编号为%s的函数执行权'% func_id)
return inner()
return outer
@login_auth('1')
def func1():
print('from func1')
func1()
生成器对象
1.本质其实就是迭代器对象
只不过迭代器是解释器提供给我的(现成的)
生成器是我们自己定义出来的(自己动手)
__iter__和__next__
2.学习生成器对象的目的是为了优化代码
一种不依赖于索引取值的通用方式
可以节省数据类型的内存占用空间(主要)
3.生成器对象代码实现
def index():
print('您哪位')
yield 111.222,333
print('您到底哪位呀')
yield 222
print('了解')
yield 333
"""
当函数体代码中有yiled关键字
那么函数名第一次加括号调用不会执行函数体代码
而是由普通的函数变成了迭代器对象(生成器)的返回值
"""
print(index) # <function index at 0x000001DEE3449550>
res = index()
print(res) # <generator object index at 0x00000222D6E16A50>
res.__next__() # 您哪位
res.__next__() # 您到底哪位呀
res.__next__() # 了解
"""
yield可以在函数体代码中出现多次
每次调用__next__方法都会从上往下执行知道遇到yield代码停留在此处
"""
print(res.__next__())
print(res.__next__())
print(res.__next__())
print(res.__next__())
"""
yield后面如果有数据值 则会像return一样返回出去
如果有多个数据值逗号隔开 那么也会自动组织成元组返回
"""
4.练习
# 编写生成器 实现range方法的功能
# 1.可以先写两个参数的功能编写 range(1,0)
def my_range(start_num,end_num):
while start_num < end_num:
yield start_num
start_num += 1
for i in my_range(1,10):
print(i)
# 2.再考虑一个参数的情况 range(10) range(0,10)
def my_range(start_num,end_num=None): # my_range(10)
if not end_num:
end_num = start_num
start_num = 0
while start_num < end_num:
yield start_num
start_num += 1
for i in my_range(100):
print(i)
# 3.最后考虑三个参数的情况 range(1,10,2)
def my_range(start_num, end_num=None,step=1): # my_range(1,10,3)
if step < 1:
step = 1
if not end_num:
end_num = start_num
start_num = 0
while start_num < end_num:
yield start_num
start_num += step
for i in my_range(1,100,2):
print(i)
for i in my_range(1,5):
print(i)
for i in my_range(10):
print(i)
for i in my_range(1,100,-2):
print(i)
yield其他用法
def index(name,food=None):
print(f'{name}准备饭饭')
while True:
food = yield
print(f'{name}正在吃{food}')
res = index('curry')
res.__next__()
res.__send('汉堡') # 传值并自动调用__next__方法
res.__send('烧烤') # 传值并自动调用__next__方法
res.__send('火锅') # 传值并自动调用__next__方法
生成器表达式
l1 = [i**2 for i in range(10) if i > 3]
print(l1) # [16, 25, 36, 49, 64, 81]
l1 = (i**2 for i in range(10) if i > 3)
print(l1) #<generator object <genexpr> at 0x000002689AA36A50>
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)
# 答案:[20, 21, 22, 23]
原创文章,作者:,如若转载,请注明出处:https://blog.ytso.com/273881.html