异常、生成器
异常常见类型
| 异常以不同的类型出现,这些类型都作为信息的一部分打印出来: 例子中的类型有 SyntaxError |
| NameError |
| IndexError |
| KeyError |
| IndentationError |
异常处理语法结构
| 1.基本句法 |
| try: |
| 待监测的代码(可能会出错的代码) |
| except 错误类型: |
| 针对上述错误类型制定的方案 |
| eg: |
| try: |
| print(x) |
| except NameError: |
| print("Variable x is not defined") |
| except: |
| print("Something else went wrong") |
| 2.查看错误的信息 |
| try: |
| 待监测的代码(可能会出错的代码) |
| except 错误类型 as e: |
| 针对上述错误类型制定的方案 |
| 3.针对不同的错误类型制定不同的解决方案 |
| try: |
| 待监测的代码(可能会出错的代码) |
| except 错误类型1 as e: |
| 针对上述错误类型1制定的方案 |
| except 错误类型2 as e: |
| 针对上述错误类型2制定的方案 |
| except 错误类型3 as e: |
| 针对上述错误类型3制定的方案 |
| 待监测的代码(可能会出错的代码) |
| 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.基本语法结构 |
| try: |
| 待监测的代码(可能会出错的代码) |
| except 错误类型: |
| 针对上述错误类型制定的方案 |
| 2.查看错误的信息 |
| try: |
| 待监测的代码(可能会出错的代码) |
| except 错误类型 as e: |
| 针对上述错误类型制定的方案 |
| 3.针对不同的错误类型制定不同的解决方案 |
| try: |
| 待监测的代码(可能会出错的代码) |
| except 错误类型1 as e: |
| 针对上述错误类型1制定的方案 |
| except 错误类型2 as e: |
| 针对上述错误类型2制定的方案 |
| except 错误类型3 as e: |
| 针对上述错误类型3制定的方案 |
| ... |
| 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 <条件测式> ,<异常附加数据> |
| assert后面条件为假时就会报异常 |
| name = 'jason' |
| |
| assert isinstance(name, str) |
| print('哈哈哈 我就说吧 肯定是字符串') |
| name.strip() |
| |
| 2.主动抛异常 |
| raise 异常名 |
| raise 异常名,附加数据 |
| raise 类名 |
| eg: |
| name = 'jason' |
| if name == 'jason': |
| raise Exception('老子不干了') |
| else: |
| print('正常走') |
异常处理实战应用
| 1.异常处理能尽量少用就少用 |
| 2.被try监测的代码能尽量少就尽量少 |
| 3.当代码中可能会出现一些无法控制的情况报错才应该考虑使用 |
| eg: 使用手机访问网络软件 断网 |
| 编写网络爬虫程序请求数据 断网 |
| 课堂练习 |
| 使用while循环+异常处理+迭代器对象 完成for循环迭代取值的功能 |
| l1 = [11, 22, 33, 44, 55, 66, 77, 88, 99] |
| |
| iter_l1 = l1.__iter__() |
| |
| while True: |
| try: |
| print(iter_l1.__next__()) |
| except StopIteration as e: |
| break |
生成器对象
| 在 Python 中,使用了 yield 的函数被称为生成器(generator)。 |
| 跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。 |
| 在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。 |
| 调用一个生成器函数,返回的是一个迭代器对象。 |
| 1.本质 |
| 还是内置有__iter__和__next__的迭代器对象 |
| 2.区别 |
| 迭代器对象是解释器自动提供的 |
| 数据类型\文件对象>>>:迭代器对象 |
| 生成器对象是程序员编写出来的 |
| 代码、关键字>>>:迭代器对象(生成器) |
| 3.创建生成器的基本语法 |
| 函数体代码中填写yield关键字 |
| |
| |
| |
| '''1.函数体代码中如果有yield关键字 |
| 那么函数名加括号并不会执行函数体代码 |
| 会生成一个生成器对象(迭代器对象) |
| ''' |
| |
| '''2.使用加括号之后的结果调用__next__才会执行函数体代码''' |
| |
| '''3.每次执行完__next__代码都会停在yield位置 下次基于该位置继续往下找第二个yield''' |
| def my_iter(): |
| print('哈哈哈 椰子汁很好喝') |
| yield 111, 222, 333 |
| print('呵呵呵 从小喝到大') |
| yield 111, 222, 333 |
| print('嘿嘿嘿 特种兵牌还可以') |
| yield 111, 222, 333 |
| print('哼哼哼 千万别整多了 倒沫子 头发掉光光') |
| yield 111, 222, 333 |
| res = my_iter() |
| r1 = res.__next__() |
| print(r1) |
| r2 = res.__next__() |
| print(r2) |
| r3 = res.__next__() |
| print(r3) |
| r4 = res.__next__() |
| print(r4) |
| '''4.yield还有点类似于return 可以返回返回值''' |
课堂练习
| 自定义生成器对标range功能(一个参数 两个参数 三个参数 迭代器对象) |
| for i in range(1, 10): |
| print(i) |
| |
| 1.先写两个参数的 |
| 2.再写一个参数的 |
| 3.最后写三个参数 |
| |
| |
| |
| |
| def my_range(start_num,end_num=None,step=1): |
| |
| if not end_num: |
| end_num=start_num |
| start_num=0 |
| if start_num>end_num: |
| start_num,end_num=end_num,start_num |
| while start_num<end_num: |
| if step > 0: |
| yield start_num |
| start_num+=step |
| elif step<0: |
| yield end_num |
| end_num+=step |
| for i in my_range(100,50,-1): |
| print(i) |
yield冷门用法
| 在 Python 中,使用了 yield 的函数被称为生成器(generator)。 |
| 跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。 |
| 在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。 |
| 调用一个生成器函数,返回的是一个迭代器对象。 |
| def eat(name, food=None): |
| print(f'{name}准备用餐') |
| while True: |
| food = yield |
| print(f'{name}正在吃{food}') |
| |
| |
| res = eat('jason') |
| res.__next__() |
| |
| |
| |
生成器表达式
| 说白了就是生成器的简化写法 |
| l1 = [i ** 2 for i in range(100)] |
| print(l1) |
| l1 = (i ** 2 for i in range(100)) |
| print(l1) |
| for i in l1: |
| 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)) |
| """ |
| res = list(g) |
| print(res) |
| |
| |
| |
| |
| |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)