流畅的python笔记(十五)上下文管理器和else块

文件管理器自动化实战:从脚本集成到工作流优化 文件管理器作为操作系统与用户交互的核心组件,其技术演进始终围绕提升文件系统操作效率展开。其核心原理在于高效管理文件元数据、提供低延迟预览并支持工作流自动化,这直接决定了开发者和高级用户的生产力水平。从技术价值看,优秀的文件管理器通过双面板操作、快速预览和自定义脚本集成等特性,将重复性文件操作转化为自动化流程,从而在批量重命名、格式转换、同步备份等应用场景中释放巨大效能。本文以Python脚本为例,深入探讨如何将图片优化等常见任务与文件管理器深度集成,构建个性化的自动化工作流,为技术选型和效率提升提供实践框架 阅读详情

目录

前言

一、if语句之外的else块

for/else

try/else

两种变成风格:EAFP与LBYL

二、上下文管理器和with块

三、contextlib模块中的使用工具

四、使用@contextmanager


前言

本章讨论python中的流程控制特性:

  • with语句和上下文管理器,with语句会设置一个临时的上下文,交给上下文管理器对象控制,并且负责清理上下文。
  • for、while、try语句的else子句。

一、if语句之外的else块

else子句不仅能在if语句中使用,还能在for、while、try语句中使用,但在这些语句中使用时与if/else中的语义差别很大:

  • for/else。仅当for循环运行完毕时(即for循环没有被break语句中止),才运行else模块。
  • while/else。仅当while循环因为循环条件为假值而退出时(即while循环没有被break语句中止),才运行else块。
  • try/else。仅当try块中没有异常抛出时才运行else块,且else子句抛出的异常不会由前面的except子句处理。

在所有情况下,只要异常或者return、break、continue语句导致控制权跳到了复合语句的主块之外,else子句也会被跳过。

for/else

如下例子,如果找到了'banana',则break会导致控制权跳出for循环,则else子句不会执行。

try/else

不使用else的情况:

上述代码中只有当dangerous_call()不抛出异常的时候,after_call才会执行,但是这样代码结构不够清晰,try块中应该只放有可能抛出异常的语句,因此像下面这样用try/else版本更好:

现在这样很明确,try块防守的是dangerous_call可能出现的错误,而不是防守after_call。而且逻辑正确,只有当dangerous_call不抛出异常时,才会执行after_call()。

两种变成风格:EAFP与LBYL

EAFP:easier to ask for forgiveness than permission,取得原谅比获得许可容易。即先假定可以正常执行,如果假定不成立,即抛出了异常,那么捕获异常进行处理。需要使用很多的try/except。

LBYL,look before you leap,三思而后行。通常用大量的if语句进行判断,判断成功才执行。

二、上下文管理器和with块

上下文管理器对象存在的目的是管理with语句,就像迭代器对象存在的目的是为了管理for语句。

        with语句的目的是简化try/finally模式。try/finally模式用于保证try模块中代码运行完毕后执行finally模块中的操作,即便try模块中代码由于异常、return语句或sys.exit()调用而中止,也会执行finally模块中的操作。finally子句中的代码通常用于释放重要的资源,或者还原临时变更的状态。

        上下文管理器协议包含__enter__和__exit__两个方法,只要实现了__enter__和__exit__这两个方法,就能作为with语句块中的上下文管理器对象使用。with语句开始运行时,会在上下文管理器对象上调用__enter__方法。with语句运行结束后,会在上下文管理器对象上调用__exit__方法,__exit__方法来扮演finally子句的角色。

        最常见的例子就是确保关闭文件对象。

  1. fp绑定到打开的文件对象上,因为文件的__enter__方法返回self。
  2. 从fp中读取一些数据。
  3. fp变量仍然可用,即与函数和模块不同,with块并没有定义新的作用域。
  4. 可以读取fp对象的属性。
  5. 但是不能在fp上执行I/O操作,因为在with块的末尾,调用TextIOWrapper.__exit__方法把文件关闭了。

标号1处,执行with语句后边的open('mirror.py')得到的结果是上下文管理器对象(这里就是文件对象,本质是TextTOWrapper类的实例(open()函数返回类型),其__enter__方法返回self),在上下文管理器对象上调用__enter__方法使得文件对象本身被绑定在了as子句中的fp上,因为文件对象的__enter__方法返回的是self。即with把with块对象的__enter__方法的返回值绑定到as自己的fp上。

        不管控制流程以哪种方式退出with块,都会在上下文管理器对象(上边例子中即open函数返回的TextIOWrapper对象)调用__exit__方法,而不是在__enter__方法返回的对象上调用(但是上边例子中上下文管理器对象与__enter__返回的对象是同一个)。

        with语句的as子句是可选的,对open函数来说,必须加上as子句,以便获取文件的引用。不过有些上下文管理器会返回None,因为没什么有用的对象能提供给用户。

        下边例子在一个精心制作的上下文管理器对象上执行操作,以此强调上下文管理器与__enter__方法返回的对象之间的区别。

  1. 上下文管理器是LookingGlass类的实例,python在上下文管理器上调用__enter__方法,把返回结果绑定到what上。
  2. 打印一个字符串值,然后打印一个what变量的值。
  3. 打印出的内容是反向的,两个print语句打印的都是反向的。
  4. 现在with块已经执行完毕,可以看出,__enter__方法返回的值,即存储在what变量中的值,是字符串‘JABBERWOCKY’。
  5. 现在用print打印也不再是反向的。

下面是LookingGlass上下文管理类的代码实现:

  1. 除了self之外,python调用__enter__方法时不传入其他参数。
  2. 把sys.stdout.write方法保存在实例属性self.original_write中,以供后边使用。
  3. 为sys.stdout.write打猴子补丁,替换成自己编写的方法。
  4. 返回‘JABBERWOCKY’字符串,用于存入目标变量what。
  5. 用于打猴子补丁的方法,返回来打印。
  6. 如果一切正常,python调用__exit_-方法时传入的参数是None,None,None,如果抛出了异常,这三个参数是异常数据。
  7. 重复代入模块不会消耗很多资源,因为python会缓存导入的模块。
  8. 还原成原来的sys.stdout_write方法。
  9. 如果exc_type不是None,即捕获到了异常,且是ZeroDivisionError类型,则打印错误消息...
  10. 然后返回True,告诉解释器,异常已经被处理。
  11. 如果__exit__方法返回None,或者True之外的值,with块中的任何异常都会向上冒泡。

解释器调用__enter__方法时,除了隐式的self之外,不会传入任何参数,传给__exit__方法的三个参数如下:

  1. exc_type,异常类,例如ZeroDivisionError。
  2. exc_value,异常实例,有时会有参数传给异常构造方法,例如错误消息,这些参数可以使用exc_value.args获取。
  3. traceback,trackback对象。

下面在with块之外测试上下文管理类,需要我们手动调用__enter__和__exit__方法:

  1. 实例化一个上下文管理器对象。
  2. 调用上下文管理器对象的__enter__方法,这个方法会用逆序打印来接管标准输出。并返回一个字符串给变量monster。
  3. monster字符串的值判断是对的,但是打印出的True是逆序的,因为调用__enter__的时候标准输出已经被打补丁接管了。
  4. 调用上下文管理器对象的__exit__方法,还原标准输出。

三、contextlib模块中的使用工具

contextlib模块提供一些使用工具,帮助创建上下文管理器类。

  • closing,如果对象提供了close()方法,但是没有实现__enter__/__exit__协议,那么可以使用这个函数构建上下文管理器。
  • suppress,构建临时忽略指定异常的上下文管理器。
  • @contextmanager,这个装饰器把简单的生成器函数变成上下文管理器,这样就不用创建类去实现管理器协议了。
  • ContexDecorator,这是个基类,用于定义基于类的上下文管理器,这种上下文管理器也能用于装饰函数,在受管理的上下文中运行整个函数。
  • ExitStack,这个上下文管理器能进入多个上下文管理器,with块结束时,ExitStack按照后进先出的顺序调用栈中各个上下文管理器的__exit__方法。如果事先不知道with块要进入多少个上下文管理器,可以使用这个类,比如同时打开任意一个文件列表中的所有文件。

这些工具中使用最广泛的是@contextmanager装饰器,其有迷惑人的一面,即它与迭代无关,却要使用yield语句,由此可以引出协程。

四、使用@contextmanager

@contextmanager装饰器能减少创建上下文管理器类的代码量,因为不用编写一个完整的类去实现__enter__和__exit__方法,而只需实现一个有yield语句的生成器,生成想让__enter__方法返回的值。

        在使用@contextmanager装饰的生成器中,yield语句的作用是把函数的定义体分为两部分:

  1. yield语句前面的所有代码在with块开始,即解释器调用__enter__方法时执行。
  2. yield语句后边的代码在with块结束时,即调用__exit__方法时执行。

  1. 应用contextmanager装饰器。
  2. 保存原来的sys.stdout.write方法。
  3. 定义自定义的reverse_write方法。
  4. 把sys.stdout.write替换成reverse_write。
  5. 产出一个值,即__enter__方法的返回值,这个值会绑定到with语句中as子句的目标变量上,执行with块中的代码时,这个函数会在这一点暂停。
  6. 恢复标准输出,这里是__exit__方法的代码,当控制权一旦跳出with块,就会继续执行yield语句之后的代码。

实际上,contextlib.contextmanager装饰器会把函数包装成实现了__enter__和__exit__方法的类。

类的名称是_GnegeratorContextManager,其__enter__方法有如下作用:

  1. 调用生成器函数,保存生成器对象gen。
  2. 调用next(gen),执行到yield关键字所在的位置。
  3. 返回next(gen)产出的值,以便把产出的值绑定到with/as语句中的目标变量上。

with块终止时,__exit__方法会做以下几件事:

  1. 检查有没有异常传给exc_type,如果有,调用gen.throw(exception),在生成器函数定义体中包含yield关键字的那一行抛出异常。
  2. 否则,调用next(gen),继续执行生成器函数定义体中yield语句之后的代码。

上方使用生成器实现的上下文管理器有一个严重错误:如果在with块中抛出了异常,python解释器会将其捕获,然后在looking_glass函数的yield表达式里再次抛出。但是,哪里没有处理错误的代码,因此looing_glass函数会终止,永远无法恢复成原来的sys.stdout.write方法。下面例子解决这个问题:

  1.  创建一个变量,用于保存可能出现的错误消息。
  2.  处理ZeroDivisionError异常,设置一个错误消息。
  3.  撤销对sys.stdout.wirte方法做的猴子补丁。
  4.  如果设置了错误消息,就打印出来。

 

 

 

 

        

 

 

 

Python任务管理器开发实战:从创意到代码的完整实现 数据持久化是软件开发中的基础概念,通过将内存中的数据保存到持久存储介质实现数据长期保存。其核心原理涉及序列化技术和文件操作,在Python中常用JSON格式实现轻量级数据存储。这种技术价值在于确保应用重启后数据不丢失,广泛应用于配置管理、用户数据存储等场景。以任务管理器为例,通过Task类定义数据模型,TaskStorage类处理JSON文件读写,实现任务的增删改查功能。项目采用模块化设计,包含环境配置、异常处理等工程实践,帮助开发者掌握从需求分析到代码实现的完整流程。通过这个具体案例,可以学习Python 阅读详情

相关推荐

大模型上下文工程:突破对话记忆限制,构建连贯智能应用

在自然语言处理和人工智能领域,上下文理解是构建智能对话系统的核心基础。其原理在于模型通过注意力机制处理输入序列,权衡不同位置信息以生成连贯回应。这项技术的核心价值在于突破传统“一问一答”的局限,使AI能够记住历史信息、理解复杂背景,实现逻辑连贯的多轮交互。在实际应用场景中,上下文工程支撑着智能客服、个性化助手、文档问答系统等需要长期记忆和状态维护的应用。本文聚焦于大模型上下文窗口的管理策略,通过对话历史摘要、关键信息缓存、分层提示设计等工程实践,系统解决信息稀释、长度限制和成本控制等挑战,为构建可靠的长对话

weixin_30265103的博客 448

上下文管理器和else

文章目录上下文管理器和else块前言if语句之外的else块上下文管理器和with块 上下文管理器和else块 前言 文章是《流畅的Python》学习笔记与个人总结。 Python中with管理上下文的的实现是个值得深究的主题。 if语句之外的else块 平常使用最多的是条件判断语句:if else,但是else也可以在for,while,try语句中使用。 for: 仅当 for 循环运行完毕时(即 for 循环没有被 break 语句中止)才运行 else 块。 while: 仅当 while 循

奔跑的蜗牛的博客 239

AI技能上下文管理:从原理到实践,解决大模型应用中的上下文污染问题

在大模型应用开发与AI Agent构建中,上下文管理是提升协作效率与确定性的核心技术。其原理在于通过有效管理模型对话历史中加载的技能模块、工具集或知识库,防止不同任务间的信息残留与干扰,从而优化宝贵的上下文窗口资源。这项技术的核心价值在于确保AI能精准调用正确功能,避免无关信息导致的输出混乱或性能下降,尤其适用于需要切换多种专业能力的复杂场景,如代码生成、文档总结与多轮对话代理。本文聚焦于AI技能上下文污染这一具体挑战,探讨如何通过技能加载、历史维护与清理策略,在普通开发环境中实现稳定、可控的AI协作流程。

weixin_34321753的博客 516

python 上下文管理器、 else 块、@contextmanager

文章目录1. else2. with上下文管理器3. contextlib模块实用工具4. @contextmanager 装饰器 learn from 《流畅的python》 1. else for/else、while/else 和 try/else 前两者 只有在 没有被break 时,才会运行 else try 块中没有异常抛出时 才运行 else for i in range(3): print(i) else: print("finish, no break") #

Michael是个半路程序员 405

Neovim集成AI编程助手:实现终端内上下文感知编码

在软件开发领域,终端编辑器(如Vim、Neovim)因其轻量高效而备受开发者青睐。其核心原理是通过命令行界面提供快速的文本编辑能力,支持插件扩展。随着AI技术的普及,将智能助手集成到开发环境成为提升工程效率的重要方向。通过API连接OpenCode、Pi等AI模型,编辑器能够理解当前代码上下文,实现精准的代码生成与问题解答。这种技术价值在于显著减少开发者在IDE、终端和浏览器间的切换,形成流畅的编码闭环。应用场景涵盖日常代码补全、错误调试、代码重构及技术文档查询等。本文聚焦于在Neovim中配置AI插件,通

weixin_33725270的博客 528

实战演练,如何用Easyexcel合并单元格,设置字体、边框样式,并在尾行加入备注

,实现效果如下:1、多级表头合并2、表头底纹+表格边框3、合并相同数据单元格4、尾行加入备注。

Su7148的博客 1万+

python的else语句可以省略_Python拾遗 上下文管理器和else语句 --流畅的python

本文的jupyter notebook文件在这里。本文出处。上下文管理器和else块Python有一些其他语言中不常见的流程控制特性,因此也往往为人所忽视,本章讨论其中两个特性:with语句和上下文管理器for, while和try语句的else子句if以外的else语句我们习惯于if/else语句,但是往往忽略,python中for, while, try语句也能跟else子句:for当循环运行...

weixin_42137032的博客 603

VS2019集成AddressSanitizer:C++内存错误检测实战指南

在C++开发中,内存管理是核心挑战之一,涉及堆、栈和全局变量的分配与释放。其原理在于程序运行时对内存地址的访问必须严格遵循分配边界和生命周期规则,否则会导致缓冲区溢出、释放后使用等严重错误。这类问题的技术价值在于直接影响程序的稳定性、安全性和性能,是高质量软件必须攻克的基础难题。应用场景广泛,从嵌入式系统到大型服务器软件,都需要可靠的内存错误检测机制。AddressSanitizer(ASan)作为一种编译时插桩技术,通过影子内存和运行时检查,能精准定位堆缓冲区溢出、释放后使用等隐蔽错误。本文以Visual

weixin_34356310的博客 279

流畅的Python: 上下文管理器

文章目录1. 上下文管理器和with块2. contextlib模块中的实用工具3. if语句之外的else块 学习《流畅的Python》,系列博客大部分均摘自本书,仅用于交流、学习和记录。 1. 上下文管理器和with块 上下文管理器对象存在的目的是管理 with 语句,就像迭代器的存在是为了管理 for 语句一样。 with 语句的目的是简化 try/finally 模式。这种模式用于保证一...

随心写写 357

使用 pip 安装 pygame 遇到的问题

今天尝试学习使用 pygame 时,按照我的习惯一发 pip install 下去,本以为很简单的事情,没想到遇到了不少问题,顺手记录一下。 0x01. 无法找到 “SDL.h” 文件 pygame 是使用 SDL 库写就的游戏框架,自然强依赖于 SDL,我的 python@3 是使用 macOS 的 brew 管理器直接安装的,可能由于不是编译安装的问题,缺少了这个库,继续使用 brew 安...

Mitscherlich的博客 8620

手动以及使用torch.nn实现前馈神经网络实验

手动以及使用torch.nn实现前馈神经网络 手动实现前馈神经网络解决上述回归、二分类、多分类任务 利用torch.nn解决上述回归、二分类、多分类任务 在多分类任务中使用至少三种不同的激活函数 对多分类任务中的模型评估隐藏层层数和隐藏单元个数对实验结果的影响

m0_52910424的博客 9372

流畅的python(十五)—上下文管理器和else块

详述一下关于程序设计的风格 在流畅的python里面列出了关于程序的两种设计风格,分别是EAFP、LBYL。 前者叫 “取得原谅比获取许可更容易” 英文是 “easier to ask for forgiveness permission” 简称EAFP。后者叫做“三思而后行”,英文是“look before you leap”, 简称是 LBYL。 那么二者最本质的区别是什么?h...

飞奔的WSL-WLL 186

ESP32使用microPython控制240x240彩色屏幕显示中文

王铭东老师详细讲解了讲了关于240x240屏幕的一些基础东西,我这里在原功能的基础上拓展了中文显示的功能,顺带修改了实际操作过程中程序中遇到的一些问题。

m0_59452630的博客 1万+

python exit()没有定义_Python拾遗 上下文管理器和else语句 --流畅的python

本文的jupyter notebook文件在这里。本文出处。上下文管理器和else块Python有一些其他语言中不常见的流程控制特性,因此也往往为人所忽视,本章讨论其中两个特性:with语句和上下文管理器for, while和try语句的else子句if以外的else语句我们习惯于if/else语句,但是往往忽略,python中for, while, try语句也能跟else子句:for当循环运行...

weixin_39762001的博客 97

M1/M2 Mac用户看过来:不装VirtualBox,用PD虚拟机也能跑ENSP的保姆级教程

本文为M1/M2 Mac用户提供了一份不依赖VirtualBox,使用Parallels Desktop虚拟机运行ENSP的详细指南。通过ARM架构的Win10镜像选择、组件替代方案和网络配置优化,实现ENSP核心功能的高效运行,特别适合网络工程师在苹果芯片设备上进行网络模拟。

weixin_28683065的博客 411

环保 HJ212协议解析

由于是做环保相关的,有时需要对212协议进行拆包和解包。HJ212协议是一种字符串协议,数据传输通讯包主要由包头、数据段长度、数据段、CRC校验、包尾组成,其中“数据段”内容包括请求编码、系统编码、命令编码、密码、设备唯一标识、总包数、包号、指令参数。请求编码为请求的时间戳,系统编码ST统一规定为22,命令编码CN为该数据包的时间类型,访问密码、设备唯一标识在对接时由平台提供,指令参数为数据内容。通讯协议的数据结构如图4所示。 图4 通讯协议的数据结构 6.1.1通讯包结构组成 名称 类型 长度

ccf19881030的专栏 2万+

读书笔记:《流畅的Python》第15章 上下文管理器和else块

# 第15章 上下文管理器和else块 """ 本章内容提要: with语句和上下文管理器 for while try语句的else子句 """ # 15.1 先做这个,再做那个:if语句之外的else块 # else子句的行为 """ for / else 仅当for循环运行完毕(即没有被break终止)才运行else块 while / else 仅当while循环因为条件为false退出(即没有被break终止)才运行else块 try/ else 仅当t.

Morbidmuse的博客 559

华为OD机试 - 音乐小说内容重复识别 - 并查集(Java 双机位C卷 200分)

华为OD机试 双机位C卷题库疯狂收录中,刷题。

学Java,找哪吒 159

十五章

第十五章 上下文管理器和else块 这是补的一块,前面看的时候,觉的用到的机会可能不多,就没写。 15.1讲了for,while,try结合else 的用法,这一块我已经掌握了,就不重复了。 书中的原句,在所有的情况下,如果异常或者return、break、或contiune语句导致控制权跳到了复合语句的主板之外,else字句也会被跳过。 书中最后介绍了一个有意思的玩意。 在Python中,try/except不仅用于处理错误,还常用于控制流畅。为此,Python官方词汇表还定义了一个缩略词(口号)。 EA

weixin_52885548的博客 4万+

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

流畅的 Python 第二版(GPT 重译)(十)

第十八章:with、match 和 else 块 上下文管理器可能几乎与子例程本身一样重要。我们只是初步了解了它们。[…] Basic 有一个 with 语句,在许多语言中都有 with 语句。但它们的功能不同,它们都只是做一些非常浅显的事情,它们可以避免重复的点式[属性]查找,但它们不进行设置和拆卸。仅仅因为它们有相同的名称,不要认为它们是相同的东西。with 语句是一件大事。 Raymond Hettinger,Python 雄辩的传道者 本章讨论的是在其他语言中不太常见的控制流特性,因此往往在 P

龙哥盟 1782

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

第15章 上下文管理器和else块

#《流流畅的Python》第15章 上下文管理器和else块 #15.1 先做这个,再做那个:if语句之外的else块 #else子句不仅能在if语句中使用,还能在for、while和try语句中使用。 #for/else、while/else和try/else的语义关系紧密,不过与if/else差别很大。 #可是,在循环中,else的语义恰好相反:“运行这个循...

weixin_30898109的博客 137

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

《流畅的Python》9-上下文管理器,with 和 else

else 的用法 除了 if/else 外,for ,while 语句都可以使用 else 。 举例 for i in range(10): if i == 11: break else: print('magic') 含义显而易见,处理for循环里没有被处理的情况,优点是不用设置特殊标志来判断。 上下文管理器 with 语句处理的对象就是上下文...

Joovo的博客 424

流畅的python

3.8.1 set 两个集合a, b: a & b 交集 a | b 合集 a - b 差集 比直接for循环省时间 dict setdefault更新value且避免重复搜索 dict查找key非常快,同时很消耗内存 不要对字典同时进行迭代和修改。如果想扫描并修改一个字典,最好: 1.迭代,找出需要添加的内容,放入一个新字典 2.迭代结束后对原有字典进行更新 原因:往dict添加新key...

j6635788的博客 1641

『流畅的Python』第15章:上下文管理器和else块

 

weixin_34112208的博客 120

OpenHands上下文管理解决方案:Claude 3.7智能对话优化与性能提升

在AI驱动的开发工具领域,上下文窗口限制已成为制约大语言模型处理复杂任务的关键瓶颈。当开发者使用Claude 3.7等先进模型进行长对话或多轮代码生成时,常面临"对话历史超出上下文限制"的困扰,导致任务中断、上下文丢失和开发效率下降。OpenHands作为AI驱动的开发平台,通过创新的上下文管理机制,为这一行业痛点提供了系统性的解决方案。 ## 问题诊断:上下文限制的技术根源 大语言模型的上下

gitblog_00207的博客 311
上一篇: 流畅的python笔记(十四)可迭代的对象、迭代器和生成器
下一篇: 流畅的python笔记(十六)协程
罗古洞的女婿
博客等级 码龄10年 1117粉丝 125原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值