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常用随机数与随机字符串方法实例
Apr 09 Python
Python入门教程之if语句的用法
May 14 Python
使用Python编写爬虫的基本模块及框架使用指南
Jan 20 Python
python多进程控制学习小结
Oct 31 Python
Pycharm中出现ImportError:DLL load failed:找不到指定模块的解决方法
Sep 17 Python
python程序 创建多线程过程详解
Sep 23 Python
python retrying模块的使用方法详解
Sep 25 Python
详解Python修复遥感影像条带的两种方式
Feb 23 Python
浅析python标准库中的glob
Mar 13 Python
Window版下在Jupyter中编写TensorFlow的环境搭建
Apr 10 Python
Pytorch环境搭建与基本语法
Jun 03 Python
Python获取excel内容及相关操作代码实例
Aug 10 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
基于qmail的完整WEBMAIL解决方案安装详解
2006/10/09 PHP
分享PHP入门的学习方法
2007/01/02 PHP
如何使用php判断所处服务器操作系统的类型
2013/06/20 PHP
PHP IDE PHPStorm配置支持友好Laravel代码提示方法
2015/05/12 PHP
PHP + plupload.js实现多图上传并显示进度条加删除实例代码
2017/03/06 PHP
JavaScript 浏览器验证代码(来自discuz)
2010/07/17 Javascript
jquery ajax 局部无刷新更新数据的实现案例
2014/02/08 Javascript
JS运动框架之分享侧边栏动画实例
2015/03/03 Javascript
node.js读取文件到字符串的方法
2015/06/29 Javascript
js判断浏览器是否支持严格模式的方法
2016/10/04 Javascript
简单的js计算器实现
2016/10/26 Javascript
Angularjs单选框相关的示例代码
2017/08/17 Javascript
微信小程序 JS动态修改样式的实现方法
2018/12/16 Javascript
基于mpvue搭建微信小程序项目框架的教程详解
2019/04/10 Javascript
Vue数据驱动表单渲染,轻松搞定form表单
2019/07/19 Javascript
JS实现提示框跟随鼠标移动
2019/08/27 Javascript
Vue使用axios引起的后台session不同操作
2020/08/14 Javascript
JavaScript实现拖拽和缩放效果
2020/08/24 Javascript
Vue路由权限控制解析
2020/11/09 Javascript
[01:14:31]Secret vs VG 2018国际邀请赛淘汰赛BO3 第一场 8.23
2018/08/24 DOTA
详解使用Python处理文件目录的相关方法
2015/10/16 Python
Python使用PyCrypto实现AES加密功能示例
2017/05/22 Python
python中子类调用父类函数的方法示例
2017/08/18 Python
python利用re,bs4,requests模块获取股票数据
2019/07/29 Python
TensorFlow中如何确定张量的形状实例
2020/06/23 Python
CSS3实现可翻转的hover效果
2018/05/23 HTML / CSS
探索HTML5本地存储功能运用技巧
2016/03/02 HTML / CSS
英国的屈臣氏:Boots博姿
2017/12/23 全球购物
欧洲有机婴儿食品最大的市场:Organic Baby Food(供美国和加拿大)
2018/03/28 全球购物
同学会邀请书大全
2014/01/12 职场文书
搞笑婚礼主持词
2014/03/13 职场文书
房产委托公证书
2014/04/08 职场文书
2014年护理工作总结范文
2014/11/14 职场文书
乔迁新居祝福语
2019/11/04 职场文书
python 中[0]*2与0*2的区别说明
2021/05/10 Python
Windows环境下实现批量执行Sql文件
2021/10/05 SQL Server