异常处理与生成器
异常处理
异常处理语法结构
1.基本语法结构
try:
待监测的代码(感觉要BBQ的代码)
except 错误类型:
针对上述错误制定的方案 # 待监测的代码出错才会执行
2.查看错误的信息
try:
待监测的代码
except 错误类型 as e: # e就是系统提示的错误信息
针对上述错误制定的方案
3.针对不同的错误类型制定不同的解决方案
try:
待监测的代码
except 错误类型1 as e:
针对错误类型1制定的方案
except 错误类型2 as e:
针对错误类型2制定的方案
...
4.万能异常 Exception\BaseException
try:
待监测的代码
except Exception as e:
针对各种常见的错误类型做统一的处理
5.结合else使用
try:
待监测的代码
except Exception as e:
针对各种常见的错误类型做统一的处理
else:
try的子代码正常运行结束且没有报错后执行的else子代码
6.结合finally一起使用
try:
待监测的代码
except Exception as e:
针对各种常见的错误类型做统一的处理
else:
try的子代码正常运行结束且没有报错后执行的else子代码
finally:
无论try的子代码是否报错最后都要执行finally子代码
异常处理补充
1.断言 assert 用于判断一段代码能不能正常运行
a = 1
assert isinstance(a, str) # 判断错误,报错,错误类型 AssertionError
assert isinstance(a, int) # 判断正确,继续执行后面的代码
2.主动抛异常 raise 需要和Exception配合使用
a = 1
if a == 1:
raise Exception('好数字')
else:
print('不咋地')
# 代码本来没有问题,但是加了raise Exception后代码在运行到这里时会主动报错,错误类型为Exception
异常处理的实战应用
使用while循环+异常处理+迭代器对象完成for循环的功能
l1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
iter_l1 = iter(l1)
while True:
try:
print(next(iter_l1))
except Exception as e: # 这里的Exception可以换成可能会出现的错误类型
break
生成器
生成器对象
1.本质
其实还是内置有__iter__和__next__方法的迭代器对象
2.生成器对象和迭代器对象的区别
迭代器对象是由解释器提供的,早就已经定义好了,直接用就行
str\list\dict\set\tuple\文件
生成器对象是由程序员自己编写出来的
3.创建生成器的基本语法
函数体代码中加 yield 关键字
def my_iter():
print('我是生成器')
yield
# 此时函数体代码中有关键字 yield 那么函数名加括号调用以后并不会执行函数体代码, 而是生成一个生成器对象
my_iter().__next__
# 使用加括号之后的结果调用__iter__才会执行函数体代码,且每次执行完__iter__方法后代码都会停留在yield位置,下次基于该位置继续执行函数体代码
def my_iter():
print('我在这里')
yield 1
print('我跑到这里来了')
yield 2
print('我又跑到这里来了')
yield 3
'''生成器调用__iter__方法的错误写法'''
my_iter().__next__() # 我在这里
my_iter().__next__() # 我在这里
my_iter().__next__() # 我在这里
# 出现这种情况是因为my_iter本身是一个函数,my_iter加括号以后本来是执行函数体代码的,但是函数体代码中有yield,my_iter()就变成了一个生成器对象,只有在调用__next__方法后才会执行函数体代码,这里使用了三个my_iter()就相当于每次都是新生成的生成器对象
'''正确写法'''
res = my_iter()
# 先把函数名加括号生成的生成器对象赋值给一个变量名,然后通过这个变量名调用__next__方法
r1 = next(res) # 我在这里
print(r1) # 1
r2 = next(res) # 我跑到这里来了
print(r2) # 2
r3 = next(res) # 我又跑到这里来了
print(r3) # 3
# yield 还有return的功能可以返回返回值
yield冷门用法
def eat(name, food=None):
print(f'{name}准备吃饭')
while True:
food = yield
print(f'{name}想吃{food}')
res = eat('李小贱', '泡面')
res.__next__() # 李小贱准备吃饭
res.__next__() # 李小贱想吃None
# 正常情况下如果我们想执行函数体代码就像上面这样,但是执行完以后,'泡面'没有传进去,这是因为 food = yield 这种结构没办法直接传值需要改成下面这样
res = eat('李小贱')
res.__next__()
res.send('泡面')
生成器表达式
l1 = (i for i in range(10)) # 生成器对象
随堂练习
自定义生成器对标range功能
def my_range(start_range, end_range=None,step=1):
# 4.考虑传的第三个参数为负数时
if step > 0:
# 2.考虑传一个参数时
if not end_range:
end_range = start_range
start_range = 1
# 1.先考虑传两个参数时
while start_range < end_range:
yield start_range
# 3.传三个参数时只需要用step替换原本的1就可以了
start_range += step
elif step < 0:
while start_range > end_range:
yield start_range
start_range += step
# for i in my_range(10):
# print(i)
# for i in my_range(1, 10):
# print(i)
# for i in my_range(1,10,2):
# print(i)
# for i in my_range(100, 50, -1):
# print(i)
标签:__,处理,my,代码,生成器,iter,range,异常
From: https://www.cnblogs.com/zyg111/p/16800210.html