目录

什么是上下文(context)

上下文管理器

实现上下文管理器的另外方式

总结


如果你有阅读源码的习惯,可能会看到一些优秀的代码经常出现带有 “with” 关键字的语句,它通常用在什么场景呢?今

对于系统资源如文件、数据库连接、socket 而言,应用程序打开这些资源并执行完业务逻辑之后,必须做的一件事就是要关闭(断开)该资源。

比如 Python 程序打开一个文件,往文件中写内容,写完之后,就要关闭该文件,否则会出现什么情况呢?极端情况下会出现 "Too many open files" 的错误,因为系统允许你打开的最大文件数量是有限的。

同样,对于数据库,如果连接数过多而没有及时关闭的话,就可能会出现 "Can not connect to MySQL server Too many connections",因为数据库连接是一种非常昂贵的资源,不可能无限制的被创建。

来看看如何正确关闭一个文件。

普通版:

def m1():f = open("output.txt", "w")f.write("python之禅")f.close()

这样写有一个潜在的问题,如果在调用 write 的过程中,出现了异常进而导致后续代码无法继续执行,close 方法无法被正常调用,因此资源就会一直被该程序占用者释放。那么该如何改进代码呢?

进阶版:

def m2():f = open("output.txt", "w")try:f.write("python之禅")except IOError:print("oops error")finally:f.close()

改良版本的程序是对可能发生异常的代码处进行 try 捕获,使用 try/finally 语句,该语句表示如果在 try 代码块中程序出现了异常,后续代码就不再执行,而直接跳转到 except 代码块。而无论如何,finally 块的代码最终都会被执行。因此,只要把 close 放在 finally 代码中,文件就一定会关闭。

高级版:

def m3():with open("output.txt", "r") as f:f.write("Python之禅")

一种更加简洁、优雅的方式就是用 with 关键字。open 方法的返回值赋值给变量 f,当离开 with 代码块的时候,系统会自动调用 f.close() 方法, with 的作用和使用 try/finally 语句是一样的。那么它的实现原理是什么?在讲 with 的原理前要涉及到另外一个概念,就是上下文管理器(Context Manager)。

什么是上下文(context)

上下文在不同的地方表示不同的含义,要感性理解。context其实说白了,和文章的上下文是一个意思,在通俗一点,我觉得叫环境更好。....

林冲大叫一声“啊也!”....

问:这句话林冲的“啊也”表达了林冲怎样的心里?

答:啊你妈个头啊!

看,一篇文章,给你摘录一段,没前没后,你读不懂,因为有语境,就是语言环境存在,一段话说了什么,要通过上下文(文章的上下文)来推断。

app点击一个按钮进入一个新的界面,也要保存你是在哪个屏幕跳过来的等等信息,以便你点击返回的时候能正确跳回,如果不存肯定就无法正确跳回了。

看这些都是上下文的典型例子,理解成环境就可以,(而且上下文虽然叫上下文,但是程序里面一般都只有上文而已,只是叫的好听叫上下文。。进程中断在操作系统中是有上有下的,不过不这个高深的问题就不要深究了。。。)

上下文管理器

任何实现了 __enter__() 和 __exit__() 方法的对象都可称之为上下文管理器,上下文管理器对象可以使用 with 关键字。显然,文件(file)对象也实现了上下文管理器。

那么文件对象是如何实现这两个方法的呢?我们可以模拟实现一个自己的文件类,让该类实现 __enter__() 和 __exit__() 方法。

class File():def __init__(self, filename, mode):self.filename = filenameself.mode = modedef __enter__(self):print("entering")self.f = open(self.filename, self.mode)return self.fdef __exit__(self, *args):print("will exit")self.f.close()

__enter__() 方法返回资源对象,这里就是你将要打开的那个文件对象,__exit__() 方法处理一些清除工作。

因为 File 类实现了上下文管理器,现在就可以使用 with 语句了。

with File('out.txt', 'w') as f:print("writing")f.write('hello, python')

这样,你就无需显示地调用 close 方法了,由系统自动去调用,哪怕中间遇到异常 close 方法也会被调用。

实现上下文管理器的另外方式

Python 还提供了一个 contextmanager 的装饰器,更进一步简化了上下文管理器的实现方式。通过 yield 将函数分割成两部分,yield 之前的语句在 __enter__ 方法中执行,yield 之后的语句在 __exit__ 方法中执行。紧跟在 yield 后面的值是函数的返回值。

from contextlib import contextmanager@contextmanager
def my_open(path, mode):f = open(path, mode)yield ff.close()

调用

with my_open('out.txt', 'w') as f:f.write("hello , the simplest context manager")

总结

Python 提供了 with 语法用于简化资源操作的后续清除操作,是 try/finally 的替代方法,实现原理建立在上下文管理器之上。此外,Python 还提供了一个 contextmanager 装饰器,更进一步简化上下管理器的实现方式。

传智播客 with与“上下文管理器” 学习笔记相关推荐

  1. 【传智播客郑州校区分享】数据库MYSQL笔记详解

    第1章 数据库 1.1 数据库概述 l 什么是数据库 数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据进行增加,修改,删除及查询操作. l 什 ...

  2. 传智播客java怎么样_零基础学习java开发选择云和好还是传智播客好?

    和我撕或者喷我真的一点意义都没有,去不去培训班,去哪个培训班跟我没有半毛钱关系,你要说你自己就是这么与众不同又努力又是一个天才真能在那一大堆人之中脱颖而出,那么恭喜你你很牛逼,不需要特别告诉我我也没啥 ...

  3. 《传智播客.Net培训.net视频教程》(.net视频asp.net培训传智播客asp.net视频教程开放课程c#视频移动开发winform SQL ADO.Net HTML JavaScript

    本资源重要通知 2011年4月传智播客.Net培训-免费公开课现场视频 [重磅内容]微软移动开发介绍1-早起的鸟儿有食吃.rar 详情 53.2MB [重磅内容]微软移动开发介绍2-windows.p ...

  4. tlias 教学过程_揭秘传智播客无缝切换线上教学,凭什么?

    在这个不平静的春节,新冠肺炎疫情牵动着全国人民的心.为了杜绝因人员聚集而引发的感染风险,全国各地启动延期开学.上班预案.面对当下线下实体班级教学困境,传智播客及时部署.全员出动,启动线上授课模式,学员 ...

  5. 我在传智播客上课的感受

    现在开始写博客,不过现在学习时间太紧,不知道能写多少呢 我在传智播客上课的感受,我是2.21班的,虽然上课没几天,但是还是挺累的,现在终于理解老师让开课前提前看视频的原因了,等着老师去讲知识与紧跟着老 ...

  6. 传智播客 .NET面试宝典(2015版)

    .Net工程师面试笔试宝典 培训班常见问题 1.你们会带着我们做完整个完整的项目吗? 答:小的项目会,大的项目则不可能, 1.众所周知,随便拿出一个中等大小的项目,也需要好多个熟练的开发人员开发好多个 ...

  7. 《2013传智播客视频》-wmv,avi,mp4.目录

    \!2013-03-14俄罗斯方块\视频\01.复习.avi; \!2013-03-14俄罗斯方块\视频\02 复习.avi; \!2013-03-14俄罗斯方块\视频\03 形状旋转.avi; \! ...

  8. 传智播客 .NET面试宝典(2014版)

    .Net工程师面试笔试宝典 由于这套面试题涉及的范围很泛,很广,很杂,大家不可能一天两天就看完和学完这套面试宝典,即使你已经学过了有关的技术,那么至少也需要一个月的时间才能消化和掌握这套面试宝典,所以 ...

  9. 传智播客Android视频教程——第三天

    传智播客Android视频教程--第三天 2012-03-29 查看应用输出的错误信息与如何部署应用到真实手机 软件安装或者运行错误,错误信息会打印在LogCat中. 可以筛选信息,pid.tag. ...

  10. php从入门到精通19天笔记,传智播客-PHP从入门到精通(19天)-video

    教程名称:传智播客-PHP从入门到精通(19天)-video 教程目录:├PHP传智社区学习资源.zip├下载必看 .txt├│  ├10目录访问权限(包括分布式权限).wmv│  ├11多站点配置. ...

最新文章

  1. 【leetcode】30. Substring with Concatenation of All Words
  2. html折线图怎么控制y轴数值,echarts Y轴数据类型不同怎么让折线图显示差距不大...
  3. 是什么使你留在你现在的公司?
  4. python灰产_Python进行目录的对比
  5. ubuntu16.04 安装kicad5.1
  6. CentOS7.1安装 Vsftpd FTP 服务器
  7. Spring Security入门(3-5)Spring Security 的鉴权 - 决策管理器和投票器
  8. 【语音合成】基于matlab GUI语音合成【含Matlab源码 293期】
  9. 【SPSS】包含多元线性回归、聚类分析、判别分析、主成分、相关系数、非参数秩检验的spss使用方法,含有相关例题,可以解决“数学建模”中数据建模的大部分问题
  10. COIN3D拖拽器使用
  11. 我们常用的软件测试工具有哪些?
  12. 有限元分析类毕业论文文献(推荐10篇)
  13. windows系统下itunes的备份路径修改
  14. 浅谈~2016的一些亮点!
  15. SSL 3.0曝出Poodle漏洞的解决方案
  16. OC作业- 图书馆管理系统
  17. 风冷精密空调安装规范
  18. 全国计算机水平考试技巧,备考计算机等级考试的技巧
  19. mac无法使用80端口问题
  20. 商女不知亡国恨,隔江犹吃炒腰花

热门文章

  1. python实例方法不可以用类调用_为什么python静态/类方法不可调用?
  2. ImportError: cannot import name 'imresize'
  3. vscode 开发maven项目(springboot项目)
  4. 以弹窗形式打开页面_“弹窗广告”肆意而为!扰民?还可能侵权!
  5. java 定义接口 xml_Java接口对接二(URL方式之xml,json,form)
  6. 安装程序无法创建新的系统分区也无法定位现有系统分区_不要再给硬盘胡乱分区了,这里有最方便安全的分区方法。...
  7. dateframe取某列数据_数据清洗amp;预处理入门完整指南
  8. ftp导入oracle,ftp向linux虚拟机传oracle安装包
  9. linux文件权限的设置命令
  10. CDN的基本原理和基础架构