异常常见类型
异常类型有很多种 异常类型就是我们一段代码在运行时遇到bug终止运行.返回给我们一段报错信息,其中就有异常类型。
SyntaxError 语法错误
NameError 名字错误
IndexError 索引错误
KeyError k键错误(字典中的k)
IndentationError 缩进错误
还有很多其他的异常类型。这里只是一小部分
异常处理语法结构
异常处理常用在我们可能会觉得出错的代码,出现异常后处理可以根据我们制定的方案执行。 异常处理的语法尽量少用,被检测的代码尽量少
需要使用关键字
try:
被监测的代码
except 错误类型:
针对上诉错误类型制定的方案
相关关键字
try/except 捕捉异常处理
else: try子代码运行整常没有报错后在执行else子代码
finally 无论try子代码是否报错都要执行finally代码
还有两个万能异常
Exception/BaseException
-------------------------------------------------------------------------------------
组合使用:
try:
name = 怎么回事 # 字符串没+引号
except NameError as e:
print('确实是傻瓜') # 错误处理后打印
else:
print('就这么回事')
finally:
print('此路是我的') # 无论try子代码是否报错都要执行
try:
可能会出问题的代码
except NameError as e:
出问题了怎么解决
else:
可能会出问题的代码没出问题走我
finally:
无论上述代码是否报错你都得走我
补充
断言 assert 就是预言的感觉, 我提前就告诉你我是啥类型,然后就执行断言下的代码,如果说错了,就报错。
name = '你猜我是啥类型'
assert isinstance(name, str)
print('就是字符串')
name.strip()
主动抛异常 根据我们给的条件 主动把错误报出
name = '我是你' '修改成我是你1号'
if name == '我是你': '不符合条件'
raise Exception('我是你') # 报错
else:
print('我不是你') '打印'
for循环底层代码
l1 = [11, 22, 33, 44, 55, 66, 77, 88]
res = iter(l1) # 使用iter方法成为 迭代器对象
while True: #循环
try:
print(res.__next__()) # 用next 方法取值,直到取完值报错
except Exception as e: # 捕捉报错并处理
break
生成器对象
其实也是含有__iter__和__next__方法的迭代器对象
和迭代器对象的区别
迭代器对象是解释器自动提供的。(之前说的迭代器对象都有哪些?字符串,列表,字典,元组,集合,文件对象)
生成器对象是程序员写出来的。(代码+关键字)
特征:
函数体代码内含有关键字yield
函数名加括号并不会执行函数体代码而产生一个生成器对象
生成器对象执行双下__next__才会走函数体代码并且遇到yield就暂停,下一次循环接着上次yleld后。
功能:
停顿代码,返回数据值,接收外部数据
生成器语法
函数体代码中填写 yield关键字
------------------------------------------------------------------------------------
def foo():
yield '第一次' # yield 具有返回值的功能,有点像return
"""当函数体代码遇到yield关键字时第一次调用并不会执行函数体代码,把函数运行状态停留在第一次遇到yield的地方,下次从第一次往下执行"""
yield '第二次'
yield '第三次'
print(foo) # <function foo at 0x00000261B5BF7A60> 一串内存地址
res = foo() # res接收foo返回值
print(res) # <generator object foo at 0x00000261B562BB30> 一串内存地址
print(next(res)) 第一次使用next 收到返回值 第一次 遇到yield不会往下继续执行
print(next(res)) 第二次 使用next 从第一次遇到yield 往下执行
print(next(res)) 第三次 使用next 从第二次遇到yield 往下执行
也可以使用for循环来取值,其本质也是next 方法取值,只不过取完值报错被for循环自动捕捉处理结束循环。
for i in res:
print(i)
""" 第一次 第二次 第三次 """
------------------------------------------------------------------------------------
def foo(): # 1 定义函数
print('第一次上课') # 4打印
yield '真爽' # 5 暂停代码 返回真爽
print('第二次上课') # 7 打印
yield '懵逼了' # 8 暂停代码 返回 懵逼了
print('第三次上课') # 10 打印
yield '慌了' # 11 暂停 返回慌了
res = foo() # 2 res 接收foo返回值
for i in res: # 3 开始循环
print(i) # 6 打印真爽 # 9 打印懵逼了 # 12 打印 慌了
结果:
第一次上课
真爽
第二次上课
懵逼了
第三次上课
慌了
"""可以看到每次循环到一个yield 都会返回该yield的返回值,然后再接着下一个yield 循环,当最后一个yield走完 接着开始下一次循环,没有获取到数据自动报错 for循环本质 捕捉到报错自动结束循环"""
------------------------------------------------------------------------------------
还可以接收外部的返回值
def eat(name):
print(f'{name}上机')
while True:
something = yield
print(f'{name}天生就是{something}')
res = eat('伞兵')
res.__next__()
res.send('被包围的')
send 可以给yield 前面的变量名传值,在自动调用__next__
结果:
伞兵上机
伞兵天生就是被包围的
生成器写range方法
def my_range(start, end = None, step=1): # start 代表开始位, end 结束位, step步长
if not end: # 判断 end是否没有值
end = start # end也绑定start的值 用在单个数值方法
start = 0 # start = 0 在把start数值改成0
while start < end: # 循环判断 start 数值是否比 end 绑定数值小
yield start # 停下循环 返回start值 给i 打印出来
start += step # 第二次for循环开始地方,第一次返回的数值加上我们设定的步长。接收whlie循环
for i in my_range(10):
print(i)
生成器表达式
就是我们上面写的生成器的简化写法
res = (返回值 for i in 可迭代对象)
特点:
1.简化代码。 2. 节省空间
eg:
1. 展示
res = (i for i in '这里是个生成器表达式')
print(res)
print(next(res)) # 这
2. 展示
res = (i+1 for i in range(5))
print(next(res)) # 1 每次使用next方法只能取一个值
生成器面试题
def add(n,i):
return n + i
def test():
for i in range(4):
yield i
# 把test函数变成生成器对象
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))
"""
res = list(g)
print(res)
A. res=[10,11,12,13]
B. res=[11,12,13,14]
C. res=[20,21,22,23]
D. res=[21,22,23,24]
选 c