文章目录
异常(exception)
什么是错误:错误是指由于逻辑或语句等导致一个程序无法正常秩序的问题
特点:有些错误是无法预知的
什么是异常:异常是程序出错时标识的一种状态,当异常发生时,程序不会再向下执行,而转去调用此函数的地方待处理此错误并恢复为正常状态。
异常的作用:
(1) 通知上层调用者有错误产生需要处理
(2) 用作信号
try语句的两种用法
(1) try-excetp语句
(2) try-finally语句
try-except语句:
语法:
try:
可能触发异常的语句
except 错误类型1 [as 变量1]
异常处理语句1
except 错误类型2 [as 变量2]
异常处理语句2
except (错误类型3, 错误类型4, …) [as 变量3]:
异常处理语句3
…
except:
异常处理语句other
else:
未发生异常时执行的语句
finally:
最终执行语句
作用:尝试捕获异常,将程序转为正常状态并继续执行
语法说明:
示例:
# 此示例示意try-except语句的用法
def div_apple(n):
print("%d个苹果您想分给几个人?" %n)
s = input("请输入人数: ")
cnt = int(s) # 可能触发ValueError错误异常
result = n / cnt # 可能触发ZeroDevisionError异常
print("每个人分了", result, "个苹果")
# 以下是调用者
# 用tr-except语句来捕获并处理ValueError, ZeroDivisionError类型的错误
try:
print("开始分苹果")
div_apple(10)
print("分苹果完成")
except ValueError:
print("dev_apple内出现了ValueError错误, 已处理")
print("用户输入不合法,苹果退回来不分了")
except ZeroDivisionError:
print("出现被零除的错误")
print("程序正常退出")
或者写成下面的形式
# 以下是调用者
# 用tr-except语句来捕获并处理ValueError, ZeroDivisionError类型的错误
try:
div_apple(10)
except (ValueError, ZeroDivisionError):
print("苹果退回来不分了")
print("程序正常退出")
try:
print("开始分苹果")
div_apple(10)
print("分苹果完成")
except ValueError as err:
print("dev_apple内出现了ValueError错误, 已处理")
print("错误信息是:", err)
except:
print("除掉ValueError类型的错误外,其他错误都可以被捕获")
else:
print("程序正常,没有进入过异常状态")
finally:
print("我是finally子句,我一定会执行的")
print("程序正常退出")
语法说明:
as子句是用于绑定错误对象的变量,可以省略不写;
except子句可以有一个或多个,但至少要有一个;
else子句最多只能有一个,也可以省略不写;
finally子句最多只能有一个,也可以省略不写
try 语句也可以写成嵌套形式:
# 此示例示意try-except语句的嵌套用法
def div_apple(n):
print("%d个苹果您想分给几个人?" %n)
s = input("请输入人数: ")
cnt = int(s) # 可能触发ValueError错误异常
# 可能触发ZeroDevisionError异常
try:
result = n / cnt
print("每个人分了", result, "个苹果")
except ZeroDevisionError:
print("被零除错误")
try:
print("开始分苹果")
div_apple(10)
print("分苹果完成")
except ValueError as err:
print("值错误,已处理")
else:
print("此try语句没有进入异常状态")
finally:
print("我是finally子句,我一定会执行的")
print("程序正常退出")
下面是python常见的异常类型:
# python全部的异常类型
ZeroDivisionError # 除(或取模)零(所有数据类型)
ValueError # 传入无效的参数
AssertionError # 断言语句失败
StopIteration # 迭代器没有更多的值
IndexError # 序列中没有此索引(index)
IndentationError # 缩进错误
OSError # 输入、输出操作失败
ImportError # 导入模块、对象失败
NameError # 未声明、初始化错误
AttributeError # 对象咩有这个属性
BaseException # 所有异常的基类
SystemExit # 解释器请求退出
KeyboardInterrupt # 用户终端执行
Exception # 常规错误的基类
GeneratorExit # 生成器发生异常来通知退出
StandardError # 所有的内建标准异常的基类
ArithmeticError # 所有数值计算错误的基类
FloatingPointError # 浮点计算错误
OverflowError # 数值运算超出最大限制
EOFError # 没有内建输入,大道EOF标记
EnvironmentError # 操作系统错误的基类
WindowsError # 系统调用失败
LookupError # 无效数据查询的基类
KeyError # 映射中没有这个键
MemoryError # 内存溢出错误
UnboundLocalError # 访问未初始化的本地变量
ReferenceError # 对象代表当一个不存在的变量被引用时发生的错误
RuntimeError # 一般的运行时错误
NotImplementedError # 尚未实现的方法
SyntaxError Python # 语法错误
TabError # Tab和空格混用
SystemError # 一般的解释器系统错误
TypeError # 对类型无效的操作
UnicodeError # Unicode相关的错误
UnicodeDecodeError # Unicode解码时的错误
UnicodeEncodeError # Unicode编码时的错误
UnicodeTranslateError # Unicode转换时错误
try_finally语句
语法:
try:
可能触发异常的语句
finally:
最终语句
说明:finally子句不可以省略,一定不存在except子句
作用:通常用try-finally语句来做触发异常时必须要处理的事情,无论异常是否发生,finally子句都会被执行
注:try-finally语句不会改变程序(正常、异常)状态
示例:
# 煎鸡蛋
# 1. 打开天然气
# 2. 煎蛋
# 3. 关闭天然气
def fry_egg():
print("打开天然气点燃。。。")
try:
count = int(input("请输入鸡蛋个数:"))
print("共煎了%d个鸡蛋" % count)
finally:
print("关闭天然气")
try:
fry_egg()
except:
print("程序已转为正常状态")
raise 语句
作用:触发一个错误,让程序进入异常状态
语法:
raise 异常类型
或
raise 异常对象
# 此示例示意raise语句来发出异常类型通知供try-except语句捕获
def make_except():
print("开始。。。")
raise ZeroDivisionError # 手动发出一个错误通知
print("结束。。。")
try:
make_except()
print("make_except调用完毕")
except ZeroDivisionError:
print("出现零除错误,已处理并转为正常状态")
# 此示例示意raise语句来发出异常对象通知供try-except语句捕获
def make_except():
print("开始。。。")
e = ZeroDivisionError("被零除!!!") # 定义标识错误信息的对象
raise e # 触发e绑定的错误,进入异常状态
print("结束。。。")
try:
make_except()
print("make_except调用完毕")
except ZeroDivisionError as err:
print("出现零除错误,已处理并转为正常状态")
print("err绑定的对象是:", err)
'''
此示例示意用raise发出错误通知给调用者
甲写了函数get_age函数
乙用户调用get_age()
'''
def get_age():
a = int(input("input age(0-140): "))
if 0 <= a <= 140:
return a
if a > 140:
raise OverflowError("人的年龄不可能大于140岁")
try:
age = get_age()
except ValueError as err:
print("用户输入的不是数字,已做相应的处理")
except OverflowError as err:
print("用户输入的年龄过大")
age = 0
print("得到的年龄是:", age)
assert 语句(断言语句)
语法:assert 真值表达式, 错误数据(通常是字符串)
作用:当真值表达式为False时,用错误数据创建一个AssertionError类型的错误,并进入异常状态。
类似于:
if 真值表达式 == False:
raise AssertionError(错误数据)
示例:
# 此示例示意assert语句的用法
def get_age():
a = int(input("input age: "))
# 以下语句在a不在[0, 140]时触发AssertionError错误
assert 0 <= a <= 140, "年龄不在合法的范围内"
return a
try:
age = get_age()
except AssertionError as e:
print("错误原因是:", e)
age = 0
print("年龄是:", age)
为什么要用异常处理机制:在程序调用层数较深时,像主调函数传递错误信息需要用return语句层层传递比较麻烦,所以用异常处理机制。
迭代器和生成器(iterator & generator)
迭代器
迭代器是指用iter(可迭代对象)函数返回的对象(实例);迭代器可以用next(it)函数获取可迭代对象的数据
迭代器函数:iter(iterable) 从可迭代对象中返回一个迭代器,iterable必须是一个能提供迭代器的可迭代对象
next(iterator)从迭代器iterator中获取下一条记录,如果无法获取下一条记录,则触发StopIteration异常。
说明:迭代器是访问可迭代对象的一种方式;迭代器只能向前取值,不会后退;用iter函数可以返回一个可迭代对象的迭代器
迭代器的用途:迭代器对象能用next函数获取下一个元素
示例:
# 用迭代器来访问可迭代对象
L = [2, 3, 5, 7]
# 用for语句来访问可迭代对象L
for x in L:
print(x)
# 用while循环来访问如下列表
it = iter(L) # 用L生成一个迭代器
while True:
try:
x = next(it)
print(x)
except StopIteration:
print("迭代终止,迭代器不能提供任何数据")
break
生成器Generator
生成器是能够动态提供数据的对象,生成器对象也是可迭代对象
生成器有两种:生成器函数和生成器表达式
生成器函数
生成器函数定义:含有yield语句的函数是生成器函数,此函数被调用时将返回一个生成器对象
注:yield翻译为产生(或生成)
yield语句
语法:yield 表达式
说明:yield用于def函数中,目的是将此函数作为生成器函数使用;yield用来生成数据,供迭代器next(it)函数使用
示例:
# 此示例示意生成器函数的定义及使用
def myyield():
'''此函数为生成器函数'''
print("即将生成2")
yield 2
print("即将生成3")
yield 3
print("即将生成5")
yield 5
print("myyield函数返回")
# 用for语句访问myyield函数
for x in myyield():
print(x)
# 用迭代器访问
gen = myyield() # gen绑定的是一个生成器(生成器一定是可迭代对象)
it = iter(gen) # it绑定迭代器
print(next(it)) # 2
生成器函数说明:生成器函数的调用将返回一个生成器对象,生成器对象是一个可迭代对象;在生成器函数调用return时会生出一个StopIteration异常通知next(it)函数不再能提供数据。
生成器表达式
语法:(表达式 for 变量 in 可迭代对象 [if 真值表达式])
注:[]里的内容可以省略
作用:用推导式的形式生成一个新的生成器
示例:
# 生成器表达式
gen = (x**2 for x in range(1, 4))
it = iter(gen)
next(it) # 1
next(it) # 4
next(it) # 9
next(it) # StopIteration
有点:不占用内存空间
列表推导式和生成器表达式的区别:
L = [1, 2, 3, 4]
gen = (x for x in L) # gen绑定生成器
lst = [x for x in L] # lst绑定列表
L[1] = 222 # 改变原列表的第二个元素
for x in lst:
print(x) # 1 2 3 4 不变
for x in gen:
print(x) # 1 222 3 4, 第二个数改变了
迭代工具函数
迭代工具函数的作用是生成一个个性化的可迭代对象
函数:
zip(iter1[, iter2, iter3, …]),返回一个zip对象对此对象用于生成一个元组,此元组的个数由最小的可迭代对象决定。
enumerate(iterable[, start]) 生成带索引的枚举对象,返回迭代类型为索引-值对(index, value)对,默认索引从零开始,也可以使用start绑定。
zip 函数
示例:
numbers = [10086, 10000, 10010, 95588]
names = ['中国移动', '中国电信', '中国联通']
for n, a, in zip(numbers, names):
print(a, '的客服号码是:', n)
# 打印出如下结果
# 中国移动 的客服号码是: 10086
# 中国电信 的客服号码是: 10000
# 中国联通 的客服号码是: 10010
d = dict(zip(names, numbers))
print(d)
for x in zip(range(10), names, numbers):
print(x)
#{'中国移动': 10086, '中国电信': 10000, '中国联通': 10010}
# (0, '中国移动', 10086)
# (1, '中国电信', 10000)
# (2, '中国联通', 10010)
zip函数的内部实现机制:
# 此示例示意zip函数的内部实现机制
def myzip(iter1, iter2):
iter1 = iter(iter1)
iter2 = iter(iter2)
while True:
x = next(iter1) #可能触发StopIteration,遇到for语句会停止
y = next(iter2) #可能触发StopIteration,遇到for语句会停止
yield (x, y)
numbers = [10086, 10000, 10010, 95588]
names = ['中国移动', '中国电信', '中国联通']
for x in myzip(numbers, names):
print(x)
enumerate函数(枚举函数)
格式:enumerate(iterable[, start])
作用:生成带索引的枚举对象,返回迭代类型为索引-值对(index, value)对,默认索引从零开始,也可以使用start绑定
names = ['中国移动', '中国电信', '中国联通']
for x in enumerate(names):
print(x)
# (0, '中国移动')
# (1, '中国电信')
# (2, '中国联通')
for x in enumerate(names):
index, element = x
print('索引', index, '对应的元素是', element)
# 索引 0 对应的元素是 中国移动
# 索引 1 对应的元素是 中国电信
# 索引 2 对应的元素是 中国联通
names = ['中国移动', '中国电信', '中国联通']
for x in enumerate(names, start=100):
print(x)
# (100, '中国移动')
# (101, '中国电信')
# (102, '中国联通')