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竟能画这么漂亮的花,帅呆了(代码分享)
Nov 15 Python
Python将list中的string批量转化成int/float的方法
Jun 26 Python
用python生成1000个txt文件的方法
Oct 25 Python
对Python Pexpect 模块的使用说明详解
Feb 14 Python
Python实现操纵控制windows注册表的方法分析
May 24 Python
Django urls.py重构及参数传递详解
Jul 23 Python
Django url,从一个页面调到另个页面的方法
Aug 21 Python
python3 requests库实现多图片爬取教程
Dec 18 Python
python实现从尾到头打印单链表操作示例
Feb 22 Python
Anaconda+VSCode配置tensorflow开发环境的教程详解
Mar 30 Python
windows+vscode安装paddleOCR运行环境的步骤
Nov 11 Python
python turtle绘图命令及案例
Nov 23 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获取程序执行的时间
2013/06/09 PHP
对比PHP对MySQL的缓冲查询和无缓冲查询
2016/07/01 PHP
PHP基于GD库实现的生成图片缩略图函数示例
2017/07/05 PHP
海量经典的jQuery插件集合
2010/01/12 Javascript
从零开始学习jQuery (二) 万能的选择器
2010/10/01 Javascript
JavaScript中使用stopPropagation函数停止事件传播例子
2014/08/27 Javascript
JavaScript调用浏览器打印功能实例分析
2015/07/17 Javascript
Jquery幻灯片特效代码分享--打开页面随机选择切换方式(3)
2015/08/15 Javascript
AngularJS中实现用户访问的身份认证和表单验证功能
2016/04/21 Javascript
基于BootStrap Metronic开发框架经验小结【八】框架功能总体界面介绍
2016/05/12 Javascript
原生js仿浏览器滚动条效果
2017/03/02 Javascript
jquery实现一个全局计时器(商城可用)
2017/06/30 jQuery
使用AngularJS编写多选按钮选中时触发指定方法的指令代码详解
2017/07/24 Javascript
Angular中自定义Debounce Click指令防止重复点击
2017/07/26 Javascript
基于jQuery实现的单行公告活动轮播效果
2017/08/23 jQuery
微信小程序使用radio显示单选项功能【附源码下载】
2017/12/11 Javascript
对layui初始化列表的CheckBox属性详解
2019/09/13 Javascript
vue-socket.io接收不到数据问题的解决方法
2020/05/13 Javascript
Python实现将一个正整数分解质因数的方法分析
2017/12/14 Python
Python编程pygame模块实现移动的小车示例代码
2018/01/03 Python
PyQt实现界面翻转切换效果
2018/04/20 Python
在PyCharm环境中使用Jupyter Notebook的两种方法总结
2018/05/24 Python
pandas 按照特定顺序输出的实现代码
2018/07/10 Python
下载官网python并安装的步骤详解
2019/10/12 Python
给 TensorFlow 变量进行赋值的方式
2020/02/10 Python
Keras设置以及获取权重的实现
2020/06/19 Python
Python 如何创建一个简单的REST接口
2020/07/30 Python
python利用opencv保存、播放视频
2020/11/02 Python
移动端html5 meta标签的神奇功效
2016/01/06 HTML / CSS
Meli Melo官网:名媛们钟爱的英国奢侈手包品牌
2017/04/17 全球购物
党员干部公开承诺书
2014/03/26 职场文书
竞选宣传委员演讲稿
2014/05/24 职场文书
干部作风建设年活动剖析材料
2014/10/23 职场文书
2015年小学中秋节活动总结
2015/03/23 职场文书
小学六年级班主任工作经验交流材料
2015/11/02 职场文书
收音机爱好者玩机13年,简评其使用过的19台收音机
2022/04/30 无线电