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实现m3u8格式转换为mp4视频格式
Feb 28 Python
Python操作mongodb数据库的方法详解
Dec 08 Python
python代码 输入数字使其反向输出的方法
Dec 22 Python
Python3的高阶函数map,reduce,filter的示例详解
Jul 23 Python
基于Python实现船舶的MMSI的获取(推荐)
Oct 21 Python
python字符串的拼接方法总结
Nov 18 Python
Python values()与itervalues()的用法详解
Nov 27 Python
Django多层嵌套ManyToMany字段ORM操作详解
May 19 Python
Python通过zookeeper实现分布式服务代码解析
Jul 22 Python
拿来就用!Python批量合并PDF的示例代码
Aug 10 Python
教你如何用python操作摄像头以及对视频流的处理
Oct 12 Python
python获取天气接口给指定微信好友发天气预报
Dec 28 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编写的SVN类
2013/07/18 PHP
分享php分页的功能模块
2015/06/16 PHP
PHP 对象接口简单实现方法示例
2020/04/13 PHP
Yii 框架入口脚本示例分析
2020/05/19 PHP
常用的javascript function代码
2008/05/23 Javascript
通过JS 获取Mouse Position(鼠标坐标)的代码
2009/09/21 Javascript
js 使FORM表单的所有元素不可编辑的示例代码
2013/10/17 Javascript
jQuery移除元素自动解绑事件实现思路及代码
2014/05/31 Javascript
JavaScript中的包装对象介绍
2015/01/27 Javascript
使用AngularJS 应用访问 Android 手机的图片库
2015/03/24 Javascript
Javascript监视变量变化的方法
2015/06/09 Javascript
jquery实现的横向二级导航效果代码
2015/08/26 Javascript
快速掌握WordPress中加载JavaScript脚本的方法
2015/12/17 Javascript
JavaScript如何实现跨域请求
2016/08/05 Javascript
基于JS实现类似支付宝支付密码输入框
2016/09/02 Javascript
jQuery 1.9版本以上的浏览器判断方法代码分享
2017/08/28 jQuery
JavaScript学习笔记之函数记忆
2017/09/06 Javascript
JS异步宏队列与微队列原理区别详解
2020/07/02 Javascript
Nuxt配置Element-UI按需引入的操作方法
2020/07/06 Javascript
vue实现公共方法抽离
2020/07/31 Javascript
实例讲解Python中global语句下全局变量的值的修改
2016/06/16 Python
Python对列表去重的多种方法(四种方法)
2017/12/05 Python
基于Python List的赋值方法
2018/06/23 Python
Django添加KindEditor富文本编辑器的使用
2018/10/24 Python
python无限生成不重复(字母,数字,字符)组合的方法
2018/12/04 Python
Python通过两个dataframe用for循环求笛卡尔积
2020/04/29 Python
降低python版本的操作方法
2020/09/11 Python
通过代码实例了解Python sys模块
2020/09/14 Python
python利用appium实现手机APP自动化的示例
2021/01/26 Python
汉米尔顿手表官网:Hamilton
2020/09/13 全球购物
Swanson中国官网:美国斯旺森健康产品公司
2021/03/01 全球购物
关联、聚合(Aggregation)以及组合(Composition)的区别
2012/02/29 面试题
事业单位个人应聘自荐信
2013/09/21 职场文书
转正申请报告格式
2015/05/15 职场文书
Nginx进程管理和重载原理详解
2021/04/22 Servers
pytorch 预训练模型读取修改相关参数的填坑问题
2021/06/05 Python