Python学习笔记六

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Katherine_hsr/article/details/83718377

异常(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, '中国联通')

猜你喜欢

转载自blog.csdn.net/Katherine_hsr/article/details/83718377