复习异常:
try: #有可能发生异常部分
print('try...')
#r = 10 / 2
r = 10 / 0
print('result:', r) #如果正常会走到这里
except ZeroDivisionError as e: #发生除零异常会走到这里 {没有就跳过except}
print('except:', e)
finally: #必定会走finally {当然,这个finally部分可以不写}
print('finally...')
print('END
')
try:
print('try...')
#r = 10 / int('0') #分母为0,ZeroDivisionError
r = 10 / int('hao') #'hao'无法转化成数字,ValueError
print('result:', r)
except ValueError as e:
print('ValueError:', e)
except ZeroDivisionError as e:
print('ZeroDivisionError:', e)
finally:
print('finally...')
print('END
')
try:
print('try...')
r = 10 / int('2')
print('result:', r)
except ValueError as e:
print('ValueError:', e)
except ZeroDivisionError as e:
print('ZeroDivisionError:', e)
else: #当所有except都没有执行就执行else,当然这个else也是可省略的
print('no error!')
finally:
print('finally...')
print('END
')
#所有的错误类型都继承自BaseException,except会把当前xxxError以及这个xxxError的子类都捕获到,
#故而设计except的时候要注意这一点,不要设计冗余无用的except分支
try:
r = 10 / int('abc')
except ValueError as e:
print('ValueError')
except UnicodeError as e: #UnicodeError是ValueError的子类,所以ValueError会把
print('UnicodeError') #UnicodeError冲掉,UnicodeError这个分支永远不会执行,故可以删去
#详细继承关系,
#见官网:https://docs.python.org/3/library/exceptions.html#exception-hierarchy
#由于异常可以穿越多层调用,层层传递,故只需要在合适的层次catch和except即可。
#比如,foo()出错了,错误被传递至bar,main,只需要在main(),catch和except就可以了。
'''
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
try:
bar('0')
except Exception as e:
print('Error:', e)
finally:
print('finally...')
'''
#错误层层上抛,形成调用栈:
# def foo(s):
# return 10 / int(s) #两类错:1.除0;2.非数字串
# def bar(s):
# return foo(s) * 2
# def main():
# bar('0')
# main()
#main()处首先报错,是由于bar()引发的,而bar()的错又是foo()引发的,根源是foo(),但
#但是可以在main()处except
#logging:既能记录错误栈,也能保证程序继续运行下去
import logging
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
try:
bar('0')
except Exception as e:
logging.exception(e) #打印错误栈信息,并且程序能够正确运行至退出
main()
print('END
') #若程序能到这里,说明前面的logging的确能支持 “程序遇到错误后,依旧正常运行”
#错误的本质是class,所以捕获错误catch到的就是这个class的一个instance
#故而我们可以继承已有的xxxError,自定义一个错误的class,并用raise在合适的时机抛出错误
class FooError(ValueError): #自定义的错误class
pass
# def foo(s):
# n = int(s)
# if n==0:
# raise FooError('invalid value: %s' % s) #防止程序往下走,因为再往下就要除0了
# return 10 / n
# foo('0')
#还有一个错误处理方式:
# def foo(s):
# n = int(s)
# if n==0:
# raise ValueError('invalid value: %s' % s)
# return 10 / n
# def bar():
# try:
# foo('0')
# except ValueError as e:
# print('ValueError!')
# raise #把ValueError原封不动地向bar()的上层抛,让调用bar()的上层处理错误
# # raise ValueError('input error') #把错误稍作处理再往上层抛
# bar()
#########################################################################################
#作业:定位错误
from functools import reduce
from decimal import *
def str2num(s): #可能s不是‘整数数字串’,引发ValueError
#return int(s) #int()要求传入 {整数数字串}
return Decimal(s) #把数字串转化成10进制的数字
def calc(exp):
ss = exp.split('+') #根据+ 把exp分割成一个list
ns = map(str2num, ss) #把这个list的每个元素由str变成int
return reduce(lambda acc, x: acc + x, ns) #等价于sum(ns)
def main():
r = calc('100 + 200 + 345')
print('100 + 200 + 345 =', r)
r = calc('99 + 88 + 7.6')
print('99 + 88 + 7.6 =', r)
main()