day14
异常 exception
什么是错误:
错误是指由于逻辑或语法等导致一个程序无法正常运行
什么是异常:
异常是指程序出错时标识的一种状态
当异常发生时,程序不会再向下执行,而转去调用此函数的地方待处理此错误并恢复为正常状态
作用:
用作信号,通知上层调用者有错误产生需要处理
异常处理语句:
try语句的两种用法:
try -except 语句
try -finally语句
try-except语法(复杂)
try:
可能出发异常的语法
except 错误类型1 [as 变量1]:
异常处理语句1
except 错误类型2 [as 变量2]:
异常处理语句2
except (错误类型3, 错误类型4):
异常处理语句3
....
except: #如果上面的所有类型都不匹配,except:
#一定可以匹配,且可以匹配任何类型
异常处理语句other
else:
未发生异常语句
finally:
最终语句
作用:
尝试捕获异常(接受异常通知),将程序转为正常状态并继承执行
语法说明:
as 子句是用于绑定错误对象的变量,可以省略
except 子句可以有一个或多个,但至少要有一个
else 子句最多只能有一个,也可以省略补不写
finally 子句最多只能有一个,也可以省略不写
示例见:
try_except.py
#代码
def div_apple(n):
print("%d个苹果您想分给几个人?"% n)
s = input('请输入人数:')
cnt = int(s) #<<--- 可能触发ValueError错误进入异常
result = n/cnt #<<---可能出触发ZeroDivisionError错误
print("每个人分了", result, "个苹果")
try:
div_apple(10)
print("分苹果完成")
except ValueError:
print("在try的内部语句中发生了值错误,已处理并转为正常状态")
except ZeroDivisionError:
print("输入的人数为零,分苹果失败")
# except (ValueError, ZeroDivisionError):
# print("分苹果失败了,苹果不分了")
print("程序正常退出")
练习一:
写一个函数 get_score()来获取学生输入的成绩(0~100的整数)
输入如果出现异常,则让此函数返回0,否则返回用户输入的成绩
注:try_except语句也可以放在函数内部使用
#代码
#方法一:在调用的地方加入异常处理语句,然后进行处理
def get_score():
sc = int(input("请输入成绩(0~100):"))
if 0 <= sc <= 100:
return sc
else:
return 0
try:
score = get_score()
except ValueError:
score = 0 #如果输入不合法,将成绩置0
print('学生的成绩是:', score)
#方法二:在函数内部有可能抛出异常的函数加上try_except语句
def get_score():
try:
sc = int(input("请输入成绩(0~100):"))
except ValueError:
score = 0
if 0 <= sc <= 100:
return sc
else:
return 0
score = get_score()
print('学生的成绩是:', score)
python全部异常类型
错误类型 说明
ZeroDivisionError 除(或取模)零 (所有数据类型)
ValueError 传入无效的参数
AssertionError 断言语句失败
StopIteration 迭代器没有更多的值
IndexError 序列中没有此索引(index)
IndentationError 缩进错误
OSError 输入/输出操作失败
ImportError 导入模块/对象失败
NameError 未声明/初始化对象 (没有属性)
AttributeError 对象没有这个属性
GeneratorExit
生成器(generator)发生异常来通知退出
TypeError 对类型无效的操作
KeyboardInterrupt 用户中断执行(通常是输入^C)
OverflowError 数值运算超出最大限制
FloatingPointError 浮点计算错误
BaseException 所有异常的基类
SystemExit 解释器请求退出
Exception 常规错误的基类
StandardError 所有的内建标准异常的基类
ArithmeticError 所有数值计算错误的基类
EOFError 没有内建输入,到达EOF 标记
EnvironmentError 操作系统错误的基类
WindowsError 系统调用失败
LookupError 无效数据查询的基类
KeyError 映射中没有这个键
MemoryError
内存溢出错误(对于Python 解释器不是致命的)
UnboundLocalError 访问未初始化的本地变量
ReferenceError
弱引用(Weak reference)试图访问已经垃圾回收了的对象
RuntimeError 一般的运行时错误
NotImplementedError 尚未实现的方法
SyntaxError Python 语法错误
TabError Tab 和空格混用
SystemError 一般的解释器系统错误
UnicodeError Unicode 相关的错误
UnicodeDecodeError Unicode 解码时的错误
UnicodeEncodeError Unicode 编码时错误
UnicodeTranslateError Unicode 转换时错误
try_finally语句
语法:
try:
可能触发异常的语句
finally:
最终语句
说明:
finally子句不可以省略
一定不存在except子句
作用:
通常try_finally语句用来做触发异常时必须要处理的事情,无论异常是否发生,finally语句都会被执行
try_finally语句不会改变程序的(正常/异常状态)
示例:
try_finally.py
#代码
def fry_egg():
print("打开天然气...")
try:
count = int(input("请输入鸡蛋个数:"))
print("完成煎鸡蛋,共煎了%d个鸡蛋!"% count)
finally:
print("关闭天然气")
try:
fry_egg()
except:
print("程序出现过异常,已转为正常状态")
print("程序正常退出")
try语句嵌套:
try嵌套是指一个try语句嵌套到另一个try语句中使用
示例:
try_embed.py
#代码
#此示例示意try语句嵌套,在内层的try语句如果已经把状态转为正常状态
#则外层的try语句将收不到错误通知
try:
try:
n = int(input("请输入整数:"))
except ValueError:
print("在内存try语句内出现错误值,已转为正常状态")
else:
print("内存try语句没有出现异常")
except:
print("外层的try语句收到异常通知,已处理并转为正常状态")
else:
print("外层try语句没有出现异常")
raise语句:
作用:
触发一个错误,让程序进入异常状态
发送错误通知给调用者
语法:
raise 异常类型
或
raise 异常对象
或
raise #重新出发上一次异常
示例:
raise.py
#代码
def make_except():
print("开始")
# raise ValueError #故意发送一个错误通知
e = ValueError("这是故意制作的一个错误!")
raise e
print("结束")
try:
make_except()
except ValueError as err: #获得错误的原因
print("make_except发出了ValueError类型的错误,已捕获")
print("错误的值是:", err)
print("程序结束")
raise2.py
#代码
def make_except():
print("开始make_except")
raise ValueError("我的一个值错误") #故意发送一个错误通知
print("结束")
def get_except():
try:
make_except()
except ValueError as err: #获得错误的原因
print("错误的值是:", err)
raise #重新触发刚收到的消息 等同于raise err
try:
get_except()
except ValueError as err:
print("get_except内部发生值错误!", err)
print("程序结束")
练习二:
写一个函数 get_age() 用来获取一个人的年龄信息
此函数规定用户只能输入1~140之间的整数,如果用户输入其他的数则直接触发ValueError类型的错误来通知调用者
#代码
def get_age():
age = int(input("请输入您的年纪:"))
if 1 <= age <= 140:
return age
else:
raise ValueError
try:
age = get_age()
print("用户的年龄是:", age)
except ValueError as err:
print("用户输入的不是1~140之间的整数,获取年龄失败!")
assert语句(断言语句)
语法:
assert 真值表达式,错误数据(通常是用字符串)
作用:
当真值表达式为False时,用错误数据创建一个AssertError类型的错误raise出去,并进入异常状态
等同于:
if 真值表达式 == False:
raise AssertError(错误数据)
示例见:
assert.py
#代码
def get_score():
s = int(input("请输入学生成绩(0~100):"))
assert 0 <= s <= 100, '成绩超出范围!!!'
#等同于
# if (0<=s<=100) == False:
# raise AssertionError('成绩超出范围!!!')
return s
try:
score = get_score()
print("学生成绩为:", score)
except ValueError:
print("用户输入的数字不能转为整数...")
except AssertionError:
print("用户输入的整数不在0~100之间...")
为什么要用异常处理机制
在程序调用层数较深时,向主函数传递错误信息需要层层return
返回比较麻烦,所以用异常处理机制
示例:
exception.py
def f1():
print("开始盖房子打地基...")
# err = ValueError("打地基挖出古物,停止施工")
# return err
print("地基完成")
def f2():
print("开始盖房子地面以上部分....")
err = ValueError("要建高压线...停止施工")
return err
print("地面以上部分完工")
def f3():
'''第一承包商开始找人盖房子'''
r = f1()
if r is not None:
return r
r = f2()
if r is not None:
return r
def build_house():
'''第一承包商开始找人盖房子'''
r = f3()
if r is not None:
return r
r = build_house()
if r is not None:
print("出错:", r)
exception2.py
def f1():
print("开始盖房子打地基...")
# err = ValueError("打地基挖出古物,停止施工")
# raise err
print("地基完成")
def f2():
print("开始盖房子地面以上部分....")
err = ValueError("要建高压线...停止施工")
raise err
print("地面以上部分完工")
def f3():
'''第一承包商开始找人盖房子'''
f1()
f2()
def build_house():
'''第一承包商开始找人盖房子'''
f3()
try:
build_house()
except ValueError as err:
print("出错:", err)
课后练习:
1.一个球从100米高空落下,每次落地后反弹高度是原高度的一半,再落下,写程序算出皮球在第十次落地后反弹的高度是多少?
打印出共经过了多少米的路程
def high(n):
return 100*(1/2)**n
def ball_high(n):
s = 100
for i in range(1,n+1):
s += high(n)*2
return s
h = high(10)
print("皮球在第十次落地后反弹的高度是:",h)
m = ball_high(10)
print("皮球共经过了{}米的路程".format(m))
2.分解质因数:输入一个正整数,分解质因数:
如:输入90
则打印: '90 = 2*3*3*5'
(质因数是指小数能被原数整除的素数(不包含1))
#方法一:
def myint():
L = []
s = ''
n = int(input("请输入一个正整数:"))
m = n
for i in range(2, n):
while True:
if n % i == 0:
L.append(str(i))
n = n/i
else:
break
s += '*'.join(L)
print(m,'=',s)
myint()
#方法二
def is_prime(x):
if x < 2:
return False
for i in range(2,x):
if x % i == 0:
return False
return True
L = [] #此列表用于存储素数
n = int(input("请输入一个正整数:"))
number = n #保存原有的数
#判断如果n不为1则找质因数
while n != 1:
for i in range(2,n+1): #依次让n除以i,如果整除则i为质因数
if n % i == 0 and is_prime(i):
L.append(i)
n = int(n/i)
break #查找当前一个质因数结束
print(L)
print(number,'=','*'.join([str(x) for x in L]),sep='')
3.修改学生信息管理系统,加入异常处理语句,让程序在任何情况下都能执行
如:输入成绩和年龄时,如果用户输入非法空字符串也不会导致程序崩溃
def input_student(L):
L = []
while True:
a = input("请输入姓名:")
if a == '':
break
try:
b = int(input("请输入年龄: "))
c = int(input("请输入成绩: "))
except ValueError:
print("您的输入有错,请重新输入:")
continue
d = {}
d["name"] = a
d['age'] = b
d['score'] = c
L.append(d)
return L