异常捕获,生成器

今日内容

异常捕获

思考

1.如何理解异常?

代码程序出现出现错误,异常而导致整个程序的停止,俗称‘bug’
  • 异常的结构

eg:

name

Traceback (most recent call last):
  File "D:/pythonProject/day21/01 生成器.py", line 13, in <module>
    name
NameError: name 'name' is not defined

结构解释

1.关键字line:

提示你异常在哪一行,当我们点File后面的蓝色字体,会自动跳转到异常的代码行

2.最后一行冒号的左边

eg:NameError:代表错误的类型

3.最后一行冒号的右边

代码错误的主要原因(改bug的关键)

  • 异常的类型
类型描述
NameError找不到指定名称的变量的时候,出现的错误
IndexError当使用超出列表范围的索引的时候,出现的错误
KeyError当使用不存在的键的时候,出现的错误
SyntaxError发生语法错误的时候,出现的错误
TypeError当在使用这种类型的场合使用另外一种类型的时候,出现的错误
  • 异常的分类

1.语法错误

不允许出现的错误,如果发现一定要及时改正

2.逻辑错误

这个是允许出现的,在发现之后修改即可

以后工作中,我们自己写完代码之后,一定要自己先测试一遍后再提交

异常捕获实参演练

思考

1.什么时候才可能会需要自己写代码处理异常?

当我们在写代码的时候,感觉这部分会报错的情况下使用

*2.如何使用异常捕获?

相当于是提前预测可能出现的问题并提前给这一部分代码进行处理
  • 异常捕获的代码实现

基本语法结构

eg:

try:
    可能会出现错误的代码
except 错误的类型 as e:
    对应错误类型做出的措施

如果你也不确定错误的类型的话,我们可以这样

eg:

try:
    可能会出现错误的代码
except 错误的类型1 as e:
    对应错误类型1做出的措施
except 错误的类型2 as e:
    对应错误类型2做出的措施
except 错误的类型3 as e:
    对应错误类型3做出的措施
  • 万能异常

关键字:Exception

在你不知道异常类型,又不想写那么多代码的情况下,可以使用

举例说明
eg:

try:
    name = 'jason'
    123 + name
except Exception as e:
    print(e)

输出结果:
unsupported operand type(s) for +: 'int' and 'str'

注意:如果出现的是语法错误的时候,使用异常处理的时候还是会正常报错

eg:

try:
    if
except Exception as e:
    print(e)

输出结果:
  File "D:/pythonProject/day21/01 生成器.py", line 23
    if
     ^
SyntaxError: invalid syntax  # SyntaxError语法错误
  • 异常捕获其他操作补充

try + else + finally

eg:

try:
    name = 'jason'
    123 + name
except Exception as e:
    print(e)
else:
    print('走我这吗?')  # 如果可能异常的代码是正确的走这
finally:
    print('都要走我这')  # 这里是有没有异常都会走这的

输出结果:
unsupported operand type(s) for +: 'int' and 'str'
都要走我这

可能异常代码正确
eg;

try:
    name = 'jason'
except Exception as e:
    print(e)
else:
    print('走我这吗?')
finally:
    print('都要走我这')

输出结果:
走我这吗?
都要走我这

断言

eg:

name = 'jason'
assert isinstance(name, list)  # name是list吗?不是
print('是这吗?')  # 当判断正确的时候,会走这

输出结果:
Traceback (most recent call last):
  File "D:/pythonProject/day21/01 生成器.py", line 33, in <module>
    assert isinstance(name, list)
AssertionError

主动异常

关键字:raise

eg:

name = input('请输入你的姓名:')
if name == 'jason':
    raise Exception('快跑')
else:
    print('没事了')

输出结果:
请输入你的姓名:jason
Traceback (most recent call last):
  File "D:/pythonProject/day21/01 生成器.py", line 42, in <module>
    raise Exception('快跑')
Exception: 快跑

请输入你的姓名:kevin
没事了

注意:异常捕获用的越少越好;被try检测的越来越少越好

  • for循环内部的本质
l1 = [11, 22, 33, 44, 55, 66, 77, 88]
res = l1.__iter__()
while True:
    try:
        print(res.__next__())  # 循环输出值
    except Exception as e:  # 如果列表中的值取完了,自动报错,异常捕获
        break  # 然后结束

生成器对象

  • 本质

    其实就是迭代器对象,只不过迭代器是解释器提供给我们的
    生成器是需要我们自己写的
    

思考

生成器的作用

也是为了节省内存空间,优化代码
一种不依赖于索引取值的方法

其实生成器是基于yield返回值的函数,支持通过双下next不断取下一个值

  • 生成器的优点和特点

    优点: 节省内存, 生成器本身就是代码. 几乎不占用内存
    特点: 惰性机制, 只能向前. 不能反复
    
  • 生成器代码实现

    举例说明

    eg:

    def index():
    	print(123)
    	yield
    
    res = index()  # 这里不是真正的调用输出,因为这里是yield将函数变为了生成器
    res.__next__()  # 123  通过双下next输出
    res.__next__()  # 没有值可取,报错
    

    eg2:

    def index():
        print(123)
        yield
        print(321)
        yield 
    
    res = index()
    res.__next__()  # 123  当运行到第一个yield停住,直到下一个双下next的出现
    res.__next__()  # 321  双下next继续输出
    

    yield后面也可以返回值

    eg:

    def index():
        print(123)
        yield 222
        print(321)
        yield 333
    
    res = index()
    print(res.__next__())  # 123 222
    print(res.__next__())  # 321 333
    

    总结
    1.当函数中出现yield的时候,那么函数名加括号第一次调用的时候是不会执行函数体代码的,而是将函数转换为生成器,也可以返回值
    2.yield也可以有多个,每次执行完一次双下next的时候都会停留在yield,等着下一个双下next的出现
    3.如果yield后面有数据值的时候,也可以像return一样返回出去,如果有多个的值的时候,也是以元组的形式返回

    eg:

    def index():
        print('jason')
        yield
    
    print(index)  # <function index at 0x0000020AD8D71E18>  函数
    res = index()  # 并没有执行函数体代码,而是将函数转换为生成器
    print(res)  # <generator object index at 0x0000020AD8EB1CA8>  生成器
    

课堂练习

  • 编写生成器,实现range的功能

    代码:

    def index(start, end=None, step=2):
    	if step < 1:  # 因为间隔数不能为负数
            step = 1  # 为负数,重新定义值
        if not end:  # None对应的布尔值为False
            end = start  # 如果只有一个参数的时候,让开始的那个数字等于end
            start = 0  # 然后让开始数为0
        while start < end:  # 条件
            yield start  # 返回出值
            start += step  # 自增
    
    
    for i in index(100):  # 循环在生成器中取值
        print(i)
    

yield其他用法

举例说明
eg:

def index(name, food=None):
    print(f'{name}吃饭')
    while True:
        food = yield 
        print(f'{name}正在吃{food}')


res = index('jason')  # 传参,转换为生成器
res.__next__()  # 输出,并停留在yield
res.send('蛋糕')  # 给yield传数据值

send可以给yield传数据值

生成器表达式

我们可以用元组的生成式来演示

结构:
	(结果	 for循环	if)

eg:

l1 = [i * 2 for i in range(10) if i > 5]
print(l1)  # [12, 14, 16, 18]  列表生成式

l1 = (i * 2 for i in range(10) if i > 5)
print(l1)  # <generator object <genexpr> at 0x0000018001F71CA8>  生成器
  • 相关面试题

    eg:

    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))
        """
    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
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值