异常与生成器
异常处理和生成器对象
-
异常语法结构
-
异常处理实战
-
生成器对象
-
生成器实现range方法
-
生成器表达式
-
生成器笔试题
-
异常简介
异常的分类:
- 语法错误
- 逻辑错误
异常结构 - 定位信息
- 错误类型
- 错误信息
- 异常常见错误类型
1. SyntexError
2. NameError
3. IndexError
4. KeyError
5. IndetationError
- 异常语法结构
try:
待监测的代码
except 错误类型
正对上述错误类型指定的方案
- 针对不同的错误类型指定不同的方案
try:
待监测的代码
except 错误类型1 as e: # e 就是报的错误类型
错误方案1
except 错误类型2 as e:
错误方案2
except 错误类型3 as e:
错误方案3
- 万能异常Exception/BaseException
# 万能异常
try:
待监测代码
except Exception as e:
常见报错都都会执行此方案
# 结合else使用
try:
待监测代码
except Exception as e:
错误执行方案
else: # 在上面的代码正常执行没有执行异常方案时执行else
print('哈哈哈,上面没有异常')
# 结合finally
try:
待监测代码
except Exception as e:
异常解决方案
else:
print('上面正常执行没有错误我就执行')
finally:
print('上面的先上,无聊他们如何我都执行')
- 断言
断言:预测上面出现的错误类型,并确定错误异常类型
name = 'wesley'
assert isinstance(name, str)
print('类型为字符串')
# 如果类型判断错误就报错
- 主动抛出异常
name = 'andy'
if name == 'andy':
raise Exception('又是你,老子不干了')
else:
print('哈哈哈不是andy,继续运行')
- 使用异常处理的注意事项
- 异常处理能尽量少用就少用
- 被try监测的代码能尽量少就尽量少
- 当代码中可能会出现一些无法控制的情况报错才应该考虑使用
- 使用异常 ,whlie循环,迭代器对象实现for循环
# 异常联系,使用while循环,异常,迭代器对象完成for循环功能
l1 = [11, 22, 33, 44, 55, 66, 77, 88, 99]
new = l1.__iter__()
while True:
try:
print(new.__next__())
except StopIteration:
break
- 生成器对象
- 生成器的本质:具有__iter__和__next__的迭代器对象
- 区别在于,迭代器是解释器提供的,生成器是程序员自己手写的
- 解释器提供
数据类型/文件对象>迭代器对象 - 程序员提供
代码,关键字>生成器对象
- 生成器语法
创建生成器就是在函数体代码中写上关键字yield
# 生成器对象
def my_iter()
print('这是一个生成器对象')
yield
# 函数体中如果有yield,第一次调用不会执行,会先生成一个生成器对象(迭代器对象)
res = my_iter()
# 加上括号后调用__next__才会执行函数体代码,并停留yield
res.__next__()
# 每次执行后都回停留在yield,等待下一个yidld
# yield也可以当做返回值使用
def my_iter():
print('我是第一')
yield 1
print('我是第二')
yield 2
print('我是第三')
yield 3
res = my_iter()
r1 = res.__next__()
print(r1)
r2 = res.__next__()
print(r2)
r3 = res.__next__()
print(r3)
- 使用生成器写reang()函数
# 先写两个参数的
def my_range(start_num, end_num=None):
if not end_num:
end_num = start_num
start_num = 0
while start_num < end_num:
yield start_num
start_num = start_num + 1
for i in my_range(10, 20):
print(i)
# 三个参数
def my_range(start_num, end_num=None, step=1):
if not end_num:
end_num = start_num
start_num = 0
if step == 1:
while start_num < end_num:
yield start_num
start_num + 1
elif step != 1:
while start_num < end_num:
yield start_num
start_num += step
for i in my_range(2, 100, 10):
print(i)
# 再来看看这个my_reang如何支持负数
def my_range(start_num, end_num=None, step=1):
if not end_num:
end_num = start_num
start_num = 0
if step == 1:
while start_num < end_num:
yield start_num
start_num + 1
elif step > 1:
while start_num < end_num:
yield start_num
start_num += step
elif step < 0:
num = abs(step)
while start_num < end_num:
yield end_num
end_num -= num
for i in my_range(2, 100, -5):
print(i)
- yield 冷门用法
def eat(name, food=None):
print(f'{name}准备用餐')
while True:
food = yield
print(f'{name}正在吃{food}')
res = eat('wesley')
res.__next__()
res.send('汉堡')
res.send('牛肉干')
# send的作用是将括号中的值传给yield的变量名再自动调用__next__
- 生成器表达式
简化代码写法
l1 = (i ** 2 for i in range(10))
print(l1) # <generator object <genexpr> at 0x100eff660>
res = l1.__iter__()
for i in res:
print(i)
- 面试题
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)
"""
第一次for循环
g = (add(n, i) for i in g)
第二次for循环
g = (add(10, i) for i in (add(10, i) for i in g))
"""
print(list(g))
[20, 21, 22, 23]