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脚本关闭文件操作的机制
Jun 28 Python
Python实现分割文件及合并文件的方法
Jul 10 Python
Python之多线程爬虫抓取网页图片的示例代码
Jan 10 Python
Python针对给定列表中元素进行翻转操作的方法分析
Apr 27 Python
python提取具有某种特定字符串的行数据方法
Dec 11 Python
python将list转为matrix的方法
Dec 12 Python
python 使用poster模块进行http方式的文件传输到服务器的方法
Jan 15 Python
python opencv判断图像是否为空的实例
Jan 26 Python
Python Flask 搭建微信小程序后台详解
May 06 Python
解决pycharm运行程序出现卡住scanning files to index索引的问题
Jun 27 Python
简单了解python的break、continue、pass
Jul 08 Python
python 比较字典value的最大值的几种方法
Apr 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
phpmyadmin的#1251问题
2006/11/25 PHP
PHP基础知识介绍
2013/09/17 PHP
header导出Excel应用示例
2014/01/24 PHP
php用户注册信息验证正则表达式
2015/11/12 PHP
Thinkphp5.0 框架视图view的比较标签用法分析
2019/10/12 PHP
jQuery中empty()方法用法实例
2015/01/16 Javascript
JS获得图片alt信息的方法
2015/04/01 Javascript
详解JavaScript中void语句的使用
2015/06/04 Javascript
jQuery插件Timelinr 实现时间轴特效
2015/10/04 Javascript
javaScript中的原型解析【推荐】
2016/05/05 Javascript
全面解析JavaScript中“&&”和“||”操作符(总结篇)
2016/07/18 Javascript
jquery实用技巧之输入框提示语句
2016/07/28 Javascript
JAVA Web实时消息后台服务器推送技术---GoEasy
2016/11/04 Javascript
原生js实现简单的Ripple按钮实例代码
2017/03/24 Javascript
基于Vue实现微信小程序的图文编辑器
2018/07/25 Javascript
深入浅析var,let,const的异同点
2018/08/07 Javascript
JavaScript图片旋转效果实现方法详解
2020/06/28 Javascript
js轮播图之旋转木马效果
2020/10/13 Javascript
python类:class创建、数据方法属性及访问控制详解
2016/07/25 Python
老生常谈Python序列化和反序列化
2017/06/28 Python
Python实现的字典值比较功能示例
2018/01/08 Python
Python中的单继承与多继承实例分析
2018/05/10 Python
Python计算库numpy进行方差/标准方差/样本标准方差/协方差的计算
2018/12/28 Python
Django组件之cookie与session的使用方法
2019/01/10 Python
python代码编写计算器小程序
2020/03/30 Python
详解如何用python实现一个简单下载器的服务端和客户端
2019/10/28 Python
Python用类实现扑克牌发牌的示例代码
2020/06/01 Python
购买原创艺术品:Zatista
2019/11/09 全球购物
俄罗斯领先的移动和数字设备在线商店:Svyaznoy.ru
2020/12/21 全球购物
Prototype是怎么扩展DOM的
2014/10/01 面试题
坚定理想信念心得体会
2014/03/11 职场文书
装饰工程师岗位职责
2014/06/08 职场文书
工会工作先进事迹
2014/08/18 职场文书
2014年学校食堂工作总结
2014/11/25 职场文书
大班下学期个人总结
2015/02/13 职场文书
Python Pygame实战之塔防游戏的实现
2022/03/17 Python