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 相关文章推荐
关于Python元祖,列表,字典,集合的比较
Jan 06 Python
Python+Socket实现基于UDP协议的局域网广播功能示例
Aug 31 Python
python进程管理工具supervisor的安装与使用教程
Sep 05 Python
tornado 多进程模式解析
Jan 15 Python
python采集微信公众号文章
Dec 20 Python
python将控制台输出保存至文件的方法
Jan 07 Python
Python序列化与反序列化pickle用法实例
Nov 11 Python
numpy 声明空数组详解
Dec 05 Python
Tensorflow的常用矩阵生成方式
Jan 04 Python
Matplotlib使用Cursor实现UI定位的示例代码
Mar 12 Python
python实现文法左递归的消除方法
May 22 Python
Python爬虫之爬取某文库文档数据
Apr 21 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
php 仿Comsenz安装效果代码打包提供下载
2010/05/09 PHP
ajax php传递和接收变量实现思路及代码
2012/12/19 PHP
深入理解curl类,可用于模拟get,post和curl下载
2013/06/08 PHP
php无限分类且支持输出树状图的详细介绍
2013/06/19 PHP
PHP连接SQLServer2005方法及代码
2013/12/26 PHP
PHP实现对站点内容外部链接的过滤方法
2014/09/10 PHP
PHP实现动态柱状图改进版
2015/03/30 PHP
php+ajax 实现输入读取数据库显示匹配信息
2015/10/08 PHP
对php 判断http还是https,以及获得当前url的方法详解
2019/01/15 PHP
JQuery autocomplete 使用手册
2010/04/01 Javascript
JS高级拖动技术 setCapture,releaseCapture
2011/07/31 Javascript
使用纯javascript实现放大镜效果
2015/03/18 Javascript
JS特效实现图片自动播放并可控的效果
2015/07/31 Javascript
js实现全国省份城市级联下拉菜单效果代码
2015/09/07 Javascript
JQuery核心函数是什么及使用方法介绍
2016/05/03 Javascript
Vue.js图片预览插件使用详解
2018/08/27 Javascript
Vue中的vue-resource示例详解
2018/11/02 Javascript
浅析vue 函数配置项watch及函数 $watch 源码分享
2018/11/22 Javascript
教你使用vue-cli快速构建的小说阅读器
2019/05/13 Javascript
javascript/jquery实现点击触发事件的方法分析
2019/11/11 jQuery
解决vue数据不实时更新的问题(数据更改了,但数据不实时更新)
2020/10/27 Javascript
[02:08]DOTA2英雄基础教程 马格纳斯
2014/01/17 DOTA
python批量复制图片到另一个文件夹
2018/09/17 Python
Django框架教程之中间件MiddleWare浅析
2019/12/29 Python
Django Haystack 全文检索与关键词高亮的实现
2020/02/17 Python
美国领先的在线邮轮旅游公司:CruiseDirect
2018/06/07 全球购物
英国皇家造币厂:The Royal Mint
2018/10/05 全球购物
c语言常见笔试题总结
2016/09/05 面试题
生产经理的自我评价分享
2013/11/07 职场文书
工业设计专业自荐书
2014/06/05 职场文书
排查整治工作方案
2014/06/09 职场文书
医院保洁服务方案
2014/06/11 职场文书
篮球社团活动总结
2014/06/27 职场文书
学校感恩节活动策划方案
2014/10/06 职场文书
大学生暑期社会实践的个人总结!
2019/07/17 职场文书
Linux安装Docker详细教程
2022/07/07 Servers