异常捕获
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:
对应错误类型1 的解决措施
except 错误类型2 as e:
对应错误类型2 的解决措施
except 错误类型3 as e:
对应错误类型3 的解决措施
except 错误类型4 as e:
3.2 万能异常(笼统的处理方式)
try :
name
d = { 'name' : 'curry' }
d[ 'pwd' ]
123 + 'hello'
except Exception as e:
print ( e)
except BaseException as e:
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 循环内部的本质
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' ] }
}
is_login = {
'is_login' : False ,
'access_list' : [ ]
}
def login_auth ( func_id) :
def outer ( func) :
def inner ( * args, ** kwargs) :
if is_login. get( 'is_login' ) :
access = is_login. get( 'access' )
if func_id in access:
res = func( * args, ** kwargs)
return res
else :
print ( '你当前没有编号为%s的函数执行权' % func_id)
else :
user_id = input ( '请输入用户编号>>>' ) . strip( )
if user_id in user_data:
username = input ( '请输入用户名>>>' ) . strip( )
pwd = input ( '请输入密码>>>' ) . strip( )
real_dict = user_data. get( user_id)
if username == real_dict. get( 'name' ) and pwd == real_dict. get( 'pwd' ) :
access = real_dict. get( 'accesss' )
is_login[ 'is_login' ] = True
is_login[ 'access_list' ] = access
if func_id in access:
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)
res = index( )
print ( res)
res. __next__( )
res. __next__( )
res. __next__( )
"""
yield可以在函数体代码中出现多次
每次调用__next__方法都会从上往下执行知道遇到yield代码停留在此处
"""
print ( res. __next__( ) )
print ( res. __next__( ) )
print ( res. __next__( ) )
print ( res. __next__( ) )
"""
yield后面如果有数据值 则会像return一样返回出去
如果有多个数据值逗号隔开 那么也会自动组织成元组返回
"""
4. 练习
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)
def my_range ( start_num, end_num= None ) :
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)
def my_range ( start_num, end_num= None , step= 1 ) :
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( '汉堡' )
res. __send( '烧烤' )
res. __send( '火锅' )
生成器表达式
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)
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)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)