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实现端口复用实例代码
Jul 03 Python
关于你不想知道的所有Python3 unicode特性
Nov 28 Python
在Python中使用Neo4j数据库的教程
Apr 16 Python
python使用multiprocessing模块实现带回调函数的异步调用方法
Apr 18 Python
Python求两个文本文件以行为单位的交集、并集与差集的方法
Jun 17 Python
详解Python中open()函数指定文件打开方式的用法
Jun 04 Python
浅谈Python中函数的参数传递
Jun 21 Python
Django框架model模型对象验证实现方法分析
Oct 02 Python
PYTHON实现SIGN签名的过程解析
Oct 28 Python
如何解决tensorflow恢复模型的特定值时出错
Feb 06 Python
Python 解析pymysql模块操作数据库的方法
Feb 18 Python
python 发送get请求接口详解
Nov 17 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
hadoop常见错误以及处理方法详解
2013/06/19 PHP
采用header定义为文件然后readfile下载(隐藏下载地址)
2014/01/31 PHP
php计算程序运行时间的简单例子分享
2014/05/10 PHP
php使用ereg验证文件上传的方法
2014/12/16 PHP
Javascript 面向对象 重载
2010/05/13 Javascript
javascript客户端解决方案 缓存提供程序
2010/07/14 Javascript
利用进制转换压缩数字函数分享
2014/01/02 Javascript
多种方法实现360浏览器下禁止自动填写用户名密码
2014/06/16 Javascript
jQuery 1.9.1源码分析系列(十三)之位置大小操作
2015/12/02 Javascript
JavaScript中this的四个绑定规则总结
2016/09/26 Javascript
Django+Vue实现WebSocket连接的示例代码
2019/05/28 Javascript
微信小程序如何实现在线客服功能
2019/10/16 Javascript
python用ConfigObj读写配置文件的实现代码
2013/03/04 Python
Python中实现常量(Const)功能
2015/01/28 Python
基于Linux系统中python matplotlib画图的中文显示问题的解决方法
2017/06/15 Python
Python实现字符串匹配的KMP算法
2019/04/04 Python
python 二维矩阵转三维矩阵示例
2019/11/30 Python
python如何随机生成高强度密码
2020/08/19 Python
使用html5+css3来实现slider切换效果告别javascript+css
2013/01/08 HTML / CSS
html5使用canvas绘制一张图片
2014/12/15 HTML / CSS
澳大利亚现代波西米亚风格女装网站:Bohemian Traders
2018/04/16 全球购物
秋季婚礼证婚词
2014/01/11 职场文书
基层干部十八大感言
2014/01/19 职场文书
空中乘务员岗位职责
2014/03/08 职场文书
班主任2015新年寄语
2014/12/08 职场文书
受资助学生感谢信
2015/01/21 职场文书
感谢信范文大全
2015/01/23 职场文书
户外亲子活动总结
2015/05/08 职场文书
教师节领导致辞
2015/07/29 职场文书
2016新年感言
2015/08/03 职场文书
竞聘书的秘诀
2019/04/02 职场文书
保安辞职申请书应该怎么写?
2019/07/15 职场文书
《天净沙·秋思》教学反思三篇
2019/11/02 职场文书
Python字符串对齐方法使用(ljust()、rjust()和center())
2021/04/26 Python
WINDOWS 64位 下安装配置mysql8.0.25最详细的教程
2022/03/22 MySQL
排查MySQL生产环境索引没有效果
2022/04/11 MySQL