[2022.7.12]异常捕获与生成器的介绍和调用

学习内容目录

  • 异常捕获

  • 自定义迭代器对象(生成器)

  • 自定义迭代器练习题

  • 生成器表达式

    学习内容详细

    异常捕获

    • 1.什么是异常?

      ​ 在程序运行过程中出现的报错 没有按正常的流程走下去 出现错误 导致程序提前结束

      也是就程序员口中的 'bug'

    • 2.异常的结构

例子:
	name  # 随便在pycharm 上输入一个错误代码
    Traceback (most recent call last):
  File "C:/pythonProject/7.11/02.py", line 20, in <module>  # ①
    name
② NameError: name 'name' is not defined ③    
# 上面就是一个报错异常 接下来 我们看一下异常的结构体  里面的关键信息

	1.标注①句子中 有line关键字 提示哪一行代码出错了
	2.标注② 冒号左边的英文提示错误类型
	3.标注③ 冒号右侧提示具体错误的原因  也是修改bug 的关键
  • 3.异常的类型
NameError  # 变量名不存在 没有赋值 报错
IndexError  # 索性超出范围 报错
KeyError  # 键不存在 报错
SyntaxError  # 错误使用标点符号 报错
TypeError  # 类型错误 对象用来表示值的类型非预期类型时发生的错误
AttributeError  # 属性错误 指引用和赋值失败时引发属性错误
  • 4.异常的分类

    语法错误:

    ​ 不允许出现 要求一旦出现立马修改 属于原则错误

    2.逻辑错误

    ​ 允许出现 最好是写好代码后自己先跑一遍 出错后以及修改

    异常捕获实参演练

    1.当自己也不确定写的代码 是否会出现异常情况

    ​ 就需要自己写下代码处理异常

    2.异常捕获就是提前察觉到代码的异常 并提前判断错误的类型 给到相对应的处理措施

    3.异常捕获的代码实现

    ​ 3.1基本的语法结构(对症下药)

    try:
       可能会出错的代码(被try监控)
    except 变量名错误 as e:  # e就是具体错误的原因
          print(e)  # 可以打印出来看到具体原因   
       对应变量名错误的解决措施
    except 键错误 as e:  
       对应键错误的解决措施
    except 标注符号错误 as e:  
       对应标注符号的解决措施
    except 索引错误 as e:  
       对应索引错误2的解决措施
    """
    针对具体的错误类型 用具体的解决措施 一一对应 """
    
    # 上述一一对应去预测判断的方式 太过于繁琐 有一种便捷
    

    ​ 3.2 万能异常

    """
    上述一一对应去预测判断的方式 太过于繁琐 有一种便捷方式 万能异常处理
    """
    	try:
        # 键错误
    	# 变量名错误
    	# 标注符号错误
    	# 索引错误
    except Exception as e:  # 万能异常方式一(推荐)
        # 对应错误的解决措施
    except BaseException as e:  # 万能异常方式二 
        # 对应错误的解决措施
    
    

    4.异常捕获其他操作补充

    4.1 elsefinally
    
    	try:
        age  # try 检测代码体的错误
    except Exception as e:
        print('变量名错了')
    else:
        print('try监测的代码没有出错的情况下正常运行结束 则会执行else子代码')
    finally:
        print('try监测的代码不管有没有出错 都会会执行finally子代码')
    4.2 断言
        	name = 'jason'  # 通过一系列的手段获取来的数据
        	assert isinstance(name, list)  # 断言数据属于什么类型 如果不对则直接报错 对则正常执行下面的代码
        	print('针对name数据使用列表相关的操作')
    4.3 主动抛出异常
    age = input('年龄输入>>>:').strip()
    if age == '18':
        raise Exception('不通过')  # raise 就是关键字 主动抛出异常 只要输入设定的值就报错
    else:
        print('不是18 可以过')
    """
      1. 在写代码的时候 异常捕获尽量不去用
      2.被try监测的代码能尽量少就尽量少 
    """
    

    异常捕获练习

    1.for 循环内部的本质
    	# 用while 循环 加异常捕获 就可以实现for循环的功能
    l1 = [1,2,3,4,5,6,7,8,9,10]
    res = l1.__iter__()
    while True:
        try:
            print(res.__next__())
        except Exception as e:
            break
    2.例题演练
    
    username = input('username>>>:').strip()
    password = input('password>>>:').strip()
    # 2.比对(循环一一比对 有一个正确就可以)
    for data in data_source:  # 'jason|123'     'kevin|321'   'oscar|222'
        real_name, real_pwd = data.split('|')  # jason 123      kevin 321 ...
        if username = real_name and password = real_pwd:
            print('登录成功')
            break  # 只要匹配正确 就应该立刻结束循环 避免资源浪费
    else:
        print('用户名或密码错误')
    结果报错:
      File "C:/pythonProject/7.11/02.py", line 71
        if username = real_name and password = real_pwd:
                    ^
    SyntaxError: invalid syntax
    """
    分析是在line71行出错的  
    出错类型是符号错误 语法错误
    找到该问题 纠正就可
    if username == real_name and password == real_pwd:
    """
    
    

    生成器对象

    1.本质
    	生成器对象本质就是迭代器对象  迭代器是由解释器提供给我们的  我们使用时直接调用就可以了
    	生成器需要我们自己去定义 也就是相当于我们需要自己去制作  __iter__   __next__
    2.生成器对象目的就是为了优化代码
    	可以不依赖索引取值的方式去做到循环取值
    	主要是可以节省数据类型的内存占用空间
    3.生成器对象代码实现的步骤
    def func():
        print('我')
        yield 
        print('你')
        yield 
        print('他')
        yield 
    """
    当函数体代码中有yield关键字
    那么函数名第一次加括号调用不会执行函数体代码
    而是由普通的函数变成了迭代器对象(生成器)  用返回值去接收一下就可以调用 __iter__   __next__ 
    """
    res = func()
    print(res)  # <generator object func at 0x01A8AB88> 已经成为生成器对象
    res.__next__()  # 我
    res.__next__()  # 你
    res.__next__()  # 他
     """
        yield可以在函数体代码中出现多次
        调用__next__方法都会从上往下执行直到遇到yield代码停留在此处
        后续再次调用时 直接从停留的地方 再次运行
        直到调用完毕后报错
     """
        def func():
        print('我')
        yield 100200300
        print('你')
        yield 90
        print('他')
        yield 80
    print(res.__next__())  # 我 (100,200,300)
    print(res.__next__())  # 你 90
    print(res.__next__())  # 他 80
     """
        yield后面如果有数据值 则会像return一样返回出去
        如果有多个数据值逗号隔开 那么也会自动组织成元组返回
     """
    
    • 课堂练习
    # 编写生成器 实现range方法的功能
    #  1.可以先以两个参数的功能编写
    # def my_range(start_num, end_num):  # 定义好两个形参 range(10)
    #     while start_num < end_num:  # 循环打印形参 start_num < end_num
    #         yield start_num  # 返回每次循环的start_num形参
    #         start_num += 1  # 每次循环打印都让形start_num自增1
    #
    # for i in my_range(1, 10):
    #     print(i)
    #  2.再考虑一个参数的情况   range(10)    range(0,10)
    # def my_range(start_num, end_num=None):  # my_range(10) 如果传入一个实参 end_unm 为默认值None 如果传入两个实参 就使用传入的参数
    #     if not end_num:  
    #         end_num = start_num
    #         start_num = 0
    #     while start_num < end_num:
    #         yield start_num
    #         start_num += 1
    # for i in my_range(10):
    #     print(i)
    # 3.最后考虑三个参数的情况   range(10)    range(0,10)  range(1, 10, 2)
    # def my_range(start_num, end_num=None, step=1):  # my_range(1,10,2) 还是用默认值形参来确定本来的规律 如果传入新的实参就用传入的值
    #     if not end_num:  
    #         end_num = start_num
    #         start_num = 0
    #     while start_num < end_num:
    #         yield start_num
    #         start_num += step  # 正常情况下是间隔1 传入新的值 让间隔几 就加几
    # for i in my_range(1, 10, 2):
    #     print(i)
    # for i in my_range(1, 5):
    #     print(i)
    # for i in my_range(10):
    #     print(i)
    

    yield其他的用法

    1.示例:
       def index(name, food=None):
        print(f'{name}准备干夜宵!!!')
        while True:
            food = yield  # send 给yield传值 赋值给到 food
            print(f'{name}正在吃{food}')
    res = index('小五')
    res.__next__()
    res.send('羊肉串')  # 小五正在吃羊肉串 关键字send 起到传值并且自动调用__next__的方法
    res.send('牛肉串')  # 小五正在吃牛肉串
    res.send('猪肉串')  # 小五正在吃猪肉串
    

    生成器表达式

    l1 = [i*2 for i in range(10) if i >2]
    print(l1)  # [6, 8, 10, 12, 14, 16, 18]
    """
    上述是列表生成式 演变一下 就可以变成生成器表达式
    """
    l1 = (i*2 for i in range(10) if i >2)
    print(l1)  # <generator object <genexpr> at 0x01FDAB88>
    print(list(l1))  # [6, 8, 10, 12, 14, 16, 18]  用列表类型转换一下就可以看到生成器表达式里所有的数据值
    
    """
    上述是列表生成式 把中括号换成小括号 就可以变成生成器表达式
    和迭代器一样 都是为了优化内存空间 都可以类比成工厂 当你需要什么的时候 工厂可以直接造给你用  随调随用 减少能源消耗 
    """
    

posted @   W日常  阅读(66)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示