异常捕获、生成器
作者:互联网
异常捕获
异常简介
1.如何理解异常?
程序员在运行代码的时候,如果出现了异常会导致整个程序的结束,异常就是程序员口中的bug
2.异常结构
2.1 关键字line所在的行:精准提示在代码的哪一行出错
2.2 最后一行冒号左侧:是错误类型
2.3 最后一行冒号右侧:是错误的具体原因(是改bug的关键)
ps:处理异常的时候,常常从下往上查看异常提示
3.异常的类型
常见的异常类型有NameError(名字错误)、IndexError(索引错误)、KeyError(键值错误)、SyntaxError(语法错误)、TypeError(类型错误)
4.异常的分类
4.1 语法错误:是不允许出现的,编写代码时标红提示就应立刻修改
4.2 逻辑错误: 是允许出现的,代码运行后报错就立刻修改
异常捕获简介
当代码不确定在未来什么时候会报错的情况下,我们可以使用异常捕获,它的使用相当于是提前预测可能出现的问题并提前给出处理的措施
异常捕获的代码实现
1. 基本语法结构(针对性强)
try:
可能会出错的代码(被try监控)
except 错误类型1 as e: # e就是具体的错误原因
对应错误类型1的解决措施
except 错误类型2 as e: # e就是具体的错误原因
对应错误类型2的解决措施
except 错误类型3 as e: # e就是具体的错误原因
对应错误类型3的解决措施
.....后面还可以写其他可能出现的错误类型,及解决措施
2. 万能异常(笼统的处理方式)
try:
可能会出错的代码(被try监控)
except Exception as e :
解决措施
try:
可能会出错的代码(被try监控)
except BaseException as e:
解决措施
ps:Exception与BaseException关系:BaseException 是 Exception 的父类
异常捕获的其他操作
1. else与 finally
try:
可能会出错的代码(被try监控)
except Exception as e:
代码出错的执行代码
else:
try监测的代码没有出错的情况下正常运行结束 则会执行else子代码
finally:
try监测的代码无论有没有出错 最后都会执行finally子代码
2. assert断言:用于判断的一个表达式,当表达式条件为false的时候回触发异常
eg:
name = 'jason' # 通过一系列的手段获取来的数据
assert isinstance(name,list) # 断言数据属于什么类型,如果不对则直接报错,如果正常就执行下面的代码
print('针对name数据使用列表相关的操作')
3. 主动抛出异常
3.3.1 raise + 异常类型 + 异常描述
3.3.2 raise + Exception +(异常描述)
eg:
name = input('请输入你的用户名>>>:').strip()
if name == 'nana':
# raise NameError('报错')
raise Exception('报错')
else:
print('不报错')
ps:异常捕获能少用就少用,且被try监测的代码能尽量少就尽量少
异常捕获练习
1.for循环内部的本质
需求:使用while+异常捕获实现for循环的功能
l1 = [1,2,3,4,5,6,7,8,9]
res = l1.__iter__()
while True:
try:
print(res.__next__())
except Exception as e:
break
2.处理异常步骤
2.1 先看具体的报错信息(异常结构的最后一行)
2.2 再看具体的定位信息(关键字line所在的行,由下往上看)
2.3 尽量将错误缩小到某个具体的变量
2.4 注意力就关注在出现这个变量的代码身上即可
生成器对象
生成器对象简介
1.生成器对象的本质其实就是迭代器对象,其区别在于迭代器对象是解释器提供给我们的,直接使用即可,而生成器则需要我们自己定义
2.学习生成器对象的目的:为了优化代码
3. 生成器对象的作用:与迭代器对象的作用一样,给我们提供了一种不依赖于索引取值的方式,并且可以节省数据类型的内存空间
生成器对象的代码实现:调用关键字yield的函数
- 当函数体代码中有yield关键字,函数名加括号进行调用,并不会执行函数体代码,而是将普通的函数变成了迭代器对象(生成器)
def func():
print("在第一个yield上面")
yield
func() # 第一次调用没有打印操作
print(func) # <function func at 0x000001DC621DB1E0> 还是函数
print(func()) # <generator object func at 0x0000021E3082EEB8> 第一次调用之后变成生成器
- yield 可以在函数体代码中出现多次,每次调用调用__next__方法都会从上往下执行,直到遇到yield代码就停住
def func():
print("在第一个yield上面")
yield
print("在第二个yield上面")
yield
print("在第三个yield上面")
yield
print("在第四个yield上面")
yield
res = func()
res.__next__() # 在第一个yield上面
res.__next__() # 在第二个yield上面
res.__next__() # 在第三个yield上面
res.__next__() # 在第四个yield上面
- 如果yield后面有返回值,则会像return一样返回出去,如果有多个数据值,并用逗号隔开,也会像return一样用元组的形式返回出去
def func():
print("在第一个yield上面")
yield 1
print("在第二个yield上面")
yield 1,2,3
print("在第三个yield上面")
yield
print("在第四个yield上面")
yield
res = func()
print(res.__next__()) # 在第一个yield上面 1
print(res.__next__()) # 在第二个yield上面 (1, 2, 3)
res.__next__() # 在第三个yield上面
res.__next__() # 在第四个yield上面
生成器对象实操
编写一个生成器 实现range方法的功能
思路:range方法可以填写一个、两个、三个参数都可以实现,为了让代码好编写,先实现两个参数,再实现一个参数,最后实现三个参数的生成器
1.两个参数的生成器
def define_range(a,b):
while a < b:
yield a
a += 1
# res = define_range(1,3)
# print(res.__next__())
# print(res.__next__())
# print(res.__next__())
ps:代码重复,考虑用for循环,并且foe循环自动调用__next__方法
for i in define_range(1,10):
print(i)
2.一个参数的生成器
def define_range(a,b = None):
if not b:
b = a
a = 0
while a < b:
yield a
a += 1
for i in define_range(10):
print(i)
3.三个参数的生成器
def define_range(a,b = None,c = 1):
if not b:
b = a
a = 0
while a < b:
yield a
a += c
for i in define_range(1,10,2):
print(i)
yield其他用法
yield不仅可以返回值,也可以接收值
def func(name,hobby = None):
print(f'欢迎{name}再次光临')
hobby = yield
print(f'你的爱好是{hobby}')
yield
res = func('nana')
res.__next__() # 欢迎nana再次光临
res.send('read') # 你的爱好是read
ps:此时send()方法会传值并且自动调用__next__方法
生成器表达式
创建一个生成器对象有两种方式,一种是调用带yield关键字的函数,另一种就是生成器表达式,与列表生成式的语法格式相同,只需要将[]换成()
1.表达式:(操作代码 for 变量名 in 迭代器对象 if 条件)
eg:
s1 = (i+3 for i in [1,2,3] )
print(s1) # <generator object <genexpr> at 0x0000024BE354EEB8>
for i in s1:
print(i) # 4 5 6
2.习题
def add(n, i):
return n + i
def test(): # 生成器
for i in range(4):
yield i
g = test() # 激活生成器
for n in [1, 10]:
g = (add(n, i) for i in g) # 此时的g只是一个生成器(<generator object ···),还没有执行__next__()方法
"""
第一次for循环
g = (add(n, i) for i in g)
第二次for循环
g = (add(n, i) for i in (add(n, i) for i in g))
"""
print(n) # 10
print(g)
res = list(g) # 内部进行for循环,自动调用了__next__方法
# g = (add(10, i) for i in (add(10, i) for i in g))
print(res) # [20, 21, 22, 23]
标签:__,res,捕获,生成器,yield,print,异常,代码 来源: https://www.cnblogs.com/luonacx/p/16471294.html