#错误&异常
程序逻辑或者语法问题产生错误,是一个事件
产生错误之后,会进入异常状态,到调用函数的地方寻找解决方法,将程序恢复为正常执行状态
异常的作用:通知上层调用者有错误发生,用作信号通知
#try语句的try-excpetion语法
try:
可能触发异常的语句
except 错误类型1 [as 变量1]:
异常处理语句
except (错误类型2,错误类型3,错误类型4):
异常处理语句
......
[except:
异常处理语句other
else:
未发生异常时动作
finally:
最终语句]
至少应该保留一个except
出现异常之后,接下来的代码将不会执行,错误将返回给上层调用者
#示例
def fenpingguo():
str1 = input("please input a num")
s = int(str1)
a = 100/s
print("over")
try:
fenpingguo()
except ValueError: #出现数值错误,即int()函数内部不是一个int字符串
print("Error")
except ZeroDivisionError: #出现除0错误
print("Error2")
except (ValueError,ZeroDivisionError) as err: #出现这两个错误,并且两个错误元组绑定在变量Error上
print(err)
except: #如果发生了其他类型的异常
print("Error occurs")
else:
print("No error occuers") #未发生异常时执行else下方的语句块
finally:
print("try have been excuted") #finally语句最终一定会被执行
#常用的Error
ZeroDivisionError
ValueError:传入无效参数
AssertionError:断言语句失败
StopIteration:迭代器没有更多索引值
IndexError:序列中没有此索引
IndentationError:缩进错误
ImportError:导入错误
NameError:未命名错误
IOError:输入输出错误
AttributeError:对象没有这个属性
BaseException:基类
SystemExit:解释器请求退出
#try-finally用法
没有except语句,只有
try:
xxx
finally:
xxx
无论是否产生异常,一定会执行finally下的语句;finally语句不会改变程序的执行状态
#raise
抛出一个错误,让程序进入异常状态
raise 异常类型
或者
raise 异常对象
比如:
def make_except():
print("function start")
myerror = ValueError("This is an ValueError")
raise myerror
print("end of function")
try:
make_except()
except ValueError:
print("Error has been dealt")
#assert 断言语句
assert 真值表达式,数据错误(通常是字符串)
当真值表达式为False时,用错误数据创建一个AssertionError类型的错误,并触发此错误并进入异常状态
相当于:
if 真值表达式 == False:
raise AssertionError(错误数据)
#迭代器 Iterator
迭代器,用于对可迭代对象做遍历的工具
两个相关函数
iter(iterable) 可从可迭代对象返回一个迭代器iterator
next(iterator) 从迭代器对象实例中获取下一个记录,如果没有下一条记录,则抛出StopInteration#
示例:用迭代器遍历一个list
for x in range(1,10,3):
print(x)
it = iter(range(1,10,3))
while True:
try:
print(next(it))
except StopIteration:
break
#生成器 Generator
生成器能够动态的提供数据对象,生成器对象也是可迭代对象
它不像列表那种静态可迭代对象,它是动态的
生成器函数的定义:
yield 表达式
yield仅用于def 函数中,该函数称为生成器函数
该函数被调用时会生成并返回一个可迭代对象,这个对象是一个生成器对象
之后每次用next访问该生成器函数,都会执行一遍非yield语句,然后返回下一个yield的值
生成器可以再生成一个迭代器,next(迭代器)时,会寻找生成器对象要数据,生成器会找生成器函数要数据,当生成器函数遇到一个yield时,会返回该值,然后生成器函数卡在这条yield函数之后,待下次取用,直到最后生成StopIteration异常
#练习题:写一个myrange代替range
def myrange(stop,start = None,step = None):
if start == None:
start = 0
else:
stop,start = start,stop
if step == None:
step = 1
if step == 0:
myerror = ValueError("argv step cannot be 0")
raise myerror
if step > 0:
while start < stop:
yield start
start += step
else:
while start > stop:
yield start
start += step
it = iter(myrange(100,150,1))
try:
while True:
print(next(it))
except ValueError as err:
print("ValueError:",err)
except StopIteration as err:
print("StopIteration Error")
print("Program exit!")
#生成器函数得到的数据现用现生成,不会占用大量内存空间!!!这是一个非常优越的优点
#python3中range本身就是这样实现的
#生成器表达式
gen = (x**2 for x in List1)
it = iter(gen)
next(it)
#迭代工具函数
生成一个个性化的可迭代对象
zip(iter1,iter2,iter3,...)用多个可迭代对象,生成一个元组,元组中每个元素也是一个元组,玫每个这样的元组即(iter1[x],iter[x],iter3[x]),x是一个确定的数,x最大是min(len(iter1),len(iter2)......)
枚举函数enumerate(iterable)
names = [1,2,3]
for x in enumerate(names):
print(x)
#练习题:输入多个字符串,打印输入的行号和字符串
l = list()
while True:
str1 = input("please input a string")
if str1 == '':
break
l.append(str1)
for x in zip(range(1,len(l)+1),l):
print("%d:%s"%(x[0],x[1]))
#练习题:用生成器函数计算斐波那契数列前n项
def fn(n):
cnt = 0
a = 1
b = 1
yield 1
cnt += 1
if cnt > n:
return
yield 1
cnt += 1
if cnt > n:
return
while True:
a,b = b,a+b
yield b
cnt += 1
if cnt > n:
return
for x in fn(20):
print(x)