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解析xml文件实例分享
Dec 04 Python
python基础教程之序列详解
Aug 29 Python
python实现的简单文本类游戏实例
Apr 28 Python
详解在Python的Django框架中创建模板库的方法
Jul 20 Python
Python中模块pymysql查询结果后如何获取字段列表
Jun 05 Python
python使用KNN算法手写体识别
Feb 01 Python
Python 脚本实现淘宝准点秒杀功能
Nov 13 Python
flask的orm框架SQLAlchemy查询实现解析
Dec 12 Python
基于python实现判断字符串是否数字算法
Jul 10 Python
Python 如何测试文件是否存在
Jul 31 Python
Python3+selenium配置常见报错解决方案
Aug 28 Python
python re模块常见用法例举
Mar 01 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 数组排序 array_multisort与uasort的区别
2011/03/24 PHP
web站点获取用户IP的安全方法 HTTP_X_FORWARDED_FOR检验
2013/06/01 PHP
php匹配字符中链接地址的方法
2014/12/22 PHP
PHP实现的简单mock json脚本分享
2015/02/10 PHP
PHP重置数组为连续数字索引的几种方式总结
2018/03/12 PHP
PHP设计模式之单例模式定义与用法分析
2019/03/26 PHP
php 使用 __call实现重载功能示例
2019/11/18 PHP
Jquery AJAX 用于计算点击率(统计)
2010/06/30 Javascript
一个分享按钮的插件使用介绍(可扩展,内附开发制作流程)
2011/09/19 Javascript
javascript背景时钟实现方法
2015/06/18 Javascript
jquery实现两个图片渐变切换效果的方法
2015/06/25 Javascript
js解决movebox移动问题
2016/03/29 Javascript
js判断数组key是否存在(不用循环)的简单实例
2016/08/03 Javascript
基于JS实现回到页面顶部的五种写法(从实现到增强)
2016/09/03 Javascript
微信小程序实现打卡日历功能
2020/09/21 Javascript
微信小程序实现简单表格
2019/02/14 Javascript
Vue编写可显示周和月模式的日历 Vue自定义日历内容的显示
2019/06/26 Javascript
用Python生成器实现微线程编程的教程
2015/04/13 Python
在Mac OS上使用mod_wsgi连接Python与Apache服务器
2015/12/24 Python
python正则分析nginx的访问日志
2017/01/17 Python
Python自动生产表情包
2017/03/17 Python
Pycharm学习教程(7)虚拟机VM的配置教程
2017/05/04 Python
Ubuntu下Python2与Python3的共存问题
2018/10/31 Python
Python如何读取文件中图片格式
2020/01/13 Python
使用jupyter Nodebook查看函数或方法的参数以及使用情况
2020/04/14 Python
Python docutils文档编译过程方法解析
2020/06/23 Python
运行Python编写的程序方法实例
2020/10/21 Python
Canvas globalCompositeOperation
2018/12/18 HTML / CSS
现在输入n个数字,以逗号,分开;然后可选择升或者降序排序;按提交键就在另一页面显示按什么排序,结果为,提供reset
2012/11/09 面试题
执行总经理岗位职责
2014/02/03 职场文书
绩效管理实施方案
2014/03/19 职场文书
房屋出租协议书
2014/04/10 职场文书
环保志愿者活动方案
2014/08/14 职场文书
2014年保育员工作总结
2014/12/02 职场文书
2015年安全教育月活动总结
2015/03/26 职场文书
Python中 range | np.arange | np.linspace三者的区别
2022/03/22 Python