Python深入学习之上下文管理器


Posted in Python onAugust 31, 2014

上下文管理器(context manager)是Python2.5开始支持的一种语法,用于规定某个对象的使用范围。一旦进入或者离开该使用范围,会有特殊操作被调用 (比如为对象分配或者释放内存)。它的语法形式是with...as...

关闭文件

我们会进行这样的操作:打开文件,读写,关闭文件。程序员经常会忘记关闭文件。上下文管理器可以在不需要文件的时候,自动关闭文件。

下面我们看一下两段程序:

# without context manager

f = open("new.txt", "w")

print(f.closed)               # whether the file is open

f.write("Hello World!")

f.close()

print(f.closed)

以及:
# with context manager

with open("new.txt", "w") as f:

    print(f.closed)

    f.write("Hello World!")

print(f.closed)

两段程序实际上执行的是相同的操作。我们的第二段程序就使用了上下文管理器 (with...as...)。上下文管理器有隶属于它的程序块。当隶属的程序块执行结束的时候(也就是不再缩进),上下文管理器自动关闭了文件 (我们通过f.closed来查询文件是否关闭)。我们相当于使用缩进规定了文件对象f的使用范围。

上面的上下文管理器基于f对象的__exit__()特殊方法(还记得我们如何利用特殊方法来实现各种语法?参看特殊方法与多范式)。当我们使用上下文管理器的语法时,我们实际上要求Python在进入程序块之前调用对象的__enter__()方法,在结束程序块的时候调用__exit__()方法。对于文件对象f来说,它定义了__enter__()和__exit__()方法(可以通过dir(f)看到)。在f的__exit__()方法中,有self.close()语句。所以在使用上下文管理器时,我们就不用明文关闭f文件了。

自定义

任何定义了__enter__()和__exit__()方法的对象都可以用于上下文管理器。文件对象f是内置对象,所以f自动带有这两个特殊方法,不需要自定义。

下面,我们自定义用于上下文管理器的对象,就是下面的myvow:

# customized object
class VOW(object):

    def __init__(self, text):

        self.text = text

    def __enter__(self):

        self.text = "I say: " + self.text    # add prefix

        return self                          # note: return an object

    def __exit__(self,exc_type,exc_value,traceback):

        self.text = self.text + "!"          # add suffix


with VOW("I'm fine") as myvow:

    print(myvow.text)
print(myvow.text)

我们的运行结果如下:

I say: I'm fine

I say: I'm fine!

我们可以看到,在进入上下文和离开上下文时,对象的text属性发生了改变(最初的text属性是"I'm fine")。

__enter__()返回一个对象。上下文管理器会使用这一对象作为as所指的变量,也就是myvow。在__enter__()中,我们为myvow.text增加了前缀 ("I say: ")。在__exit__()中,我们为myvow.text增加了后缀("!")。

注意: __exit__()中有四个参数。当程序块中出现异常(exception),__exit__()的参数中exc_type, exc_value, traceback用于描述异常。我们可以根据这三个参数进行相应的处理。如果正常运行结束,这三个参数都是None。在我们的程序中,我们并没有用到这一特性。

总结:

通过上下文管理器,我们控制对象在程序不同区间的特性。上下文管理器(with EXPR as VAR)大致相当于如下流程:

# with EXPR as VAR:
VAR = EXPR

VAR = VAR.__enter__()

try:

    BLOCK

finally:

    VAR.__exit__()

由于上下文管理器带来的便利,它是一个值得使用的工具。
Python 相关文章推荐
pip 错误unused-command-line-argument-hard-error-in-future解决办法
Jun 01 Python
Python实现二叉堆
Feb 03 Python
小小聊天室Python代码实现
Aug 17 Python
Python ldap实现登录实例代码
Sep 30 Python
Python正则表达式如何进行字符串替换实例
Dec 28 Python
Python中定时任务框架APScheduler的快速入门指南
Jul 06 Python
Django rest framework基本介绍与代码示例
Jan 26 Python
python如何实现内容写在图片上
Mar 23 Python
Python for循环与range函数的使用详解
Mar 23 Python
解决Python图形界面中设置尺寸的问题
Mar 05 Python
详解Open Folder as PyCharm Project怎么添加的方法
Dec 29 Python
python 管理系统实现mysql交互的示例代码
Dec 06 Python
Python深入学习之特殊方法与多范式
Aug 31 #Python
python中的reduce内建函数使用方法指南
Aug 31 #Python
Python中使用ConfigParser解析ini配置文件实例
Aug 30 #Python
python进阶教程之动态类型详解
Aug 30 #Python
python进阶教程之异常处理
Aug 30 #Python
python进阶教程之函数对象(函数也是对象)
Aug 30 #Python
python进阶教程之循环对象
Aug 30 #Python
You might like
sourcesafe管理phpproj文件的补充说明(downmoon)
2009/04/11 PHP
php里array_work用法实例分析
2015/07/13 PHP
php中define用法实例
2015/07/30 PHP
PHP+ajax实现上传、删除、修改单张图片及后台处理逻辑操作详解
2020/02/12 PHP
FileUpload上传图片(图片不变形)
2010/08/05 Javascript
Google 静态地图API实现代码
2010/11/19 Javascript
httpclient模拟登陆具体实现(使用js设置cookie)
2013/12/11 Javascript
JS将数字转换成三位逗号分隔的样式(示例代码)
2014/02/19 Javascript
javascript实现倒计时N秒后网页自动跳转代码
2014/12/11 Javascript
简单谈谈javascript代码复用模式
2015/01/28 Javascript
JQuery ztree带筛选、异步加载实例讲解
2016/02/25 Javascript
微信小程序 框架详解及实例应用
2016/09/26 Javascript
js 将canvas生成图片保存,或直接保存一张图片的实现方法
2018/01/02 Javascript
微信小程序从注册账号到上架(图文详解)
2019/07/17 Javascript
原生js实现ajax请求和JSONP跨域请求操作示例
2020/03/14 Javascript
JavaScript ECMA-262-3 深入解析(一):执行上下文实例分析
2020/04/25 Javascript
在Python中操作列表之List.pop()方法的使用
2015/05/21 Python
Python黑魔法@property装饰器的使用技巧解析
2016/06/16 Python
Python3实现购物车功能
2018/04/18 Python
如何在django中实现分页功能
2020/04/22 Python
remote接口和home接口主要作用
2013/05/15 面试题
课堂教学改革实施方案
2014/03/17 职场文书
共产党员公开承诺书范文
2014/03/28 职场文书
酒店总经理岗位职责范本
2014/08/08 职场文书
售房协议书
2014/08/19 职场文书
学校群众路线专项整治方案
2014/10/31 职场文书
先进基层党组织事迹材料
2014/12/25 职场文书
新郎答谢词
2015/01/04 职场文书
小学推普周活动总结
2015/05/07 职场文书
2015年中职班主任工作总结
2015/05/25 职场文书
生产设备维护保养制度
2015/08/06 职场文书
体育部部长竞选稿
2015/11/21 职场文书
《三国志》赏析
2019/08/27 职场文书
python入门学习关于for else的特殊特性讲解
2021/11/20 Python
JavaScript阻止事件冒泡的方法
2021/12/06 Javascript
html粘性页脚的具体使用
2022/01/18 HTML / CSS