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益智游戏计算汉诺塔问题示例
Mar 05 Python
Python简单实现Base64编码和解码的方法
Apr 29 Python
详解如何用OpenCV + Python 实现人脸识别
Oct 20 Python
Tensorflow 合并通道及加载子模型的方法
Jul 26 Python
python之消除前缀重命名的方法
Oct 21 Python
PyQt5固定窗口大小的方法
Jun 18 Python
python3实现用turtle模块画一棵随机樱花树
Nov 21 Python
python rolling regression. 使用 Python 实现滚动回归操作
Jun 08 Python
Win10下配置tensorflow-gpu的详细教程(无VS2015/2017)
Jul 14 Python
通过代码简单了解django model序列化作用
Nov 12 Python
Python 生成短8位唯一id实战教程
Jan 13 Python
七个Python必备的GUI库
Apr 27 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/10/25 PHP
php判断linux下程序问题实例
2015/07/09 PHP
php微信公众平台配置接口开发程序
2016/09/22 PHP
$.ajax返回的JSON无法执行success的解决方法
2011/09/09 Javascript
jquery 删除字符串最后一个字符的方法解析
2014/02/11 Javascript
浅析函数声明和函数表达式——函数声明的声明提前
2016/05/03 Javascript
chrome下判断点击input上标签还是其余标签的实现方法
2016/09/18 Javascript
前端JS面试中常见的算法问题总结
2016/12/23 Javascript
原生js实现弹出层效果
2017/01/20 Javascript
bootstrap fileinput 上传插件的基础使用
2017/02/17 Javascript
Easyui使用Dialog行内按钮布局的实例
2017/07/27 Javascript
Vue脚手架的简单使用实例
2018/07/10 Javascript
JS块级作用域和私有变量实例分析
2019/05/11 Javascript
Vue + Elementui实现多标签页共存的方法
2019/06/12 Javascript
解决mui框架中switch开关通过js控制开或者关状态时小圆点不动的问题
2019/09/03 Javascript
Vue按时间段查询数据组件使用详解
2020/08/21 Javascript
[46:23]OG vs EG 2018国际邀请赛淘汰赛BO3 第一场 8.23
2018/08/24 DOTA
Python编程实现的简单神经网络算法示例
2018/01/26 Python
Python 实现子类获取父类的类成员方法
2019/01/11 Python
Scrapy-Redis结合POST请求获取数据的方法示例
2019/05/07 Python
django API 中接口的互相调用实例
2020/04/01 Python
NEW LOOK官网:英国时装零售巨头之一,快时尚品牌
2017/01/11 全球购物
印尼美容产品购物网站:PerfectBeauty.id
2017/12/01 全球购物
正宗的澳大利亚Ugg靴子零售商:UGG Express
2020/04/19 全球购物
Wolford法国官网:奥地利奢侈内衣品牌
2020/08/11 全球购物
Made in Design意大利:现代家具、名家灯具和装饰
2020/10/27 全球购物
新闻系毕业生推荐信
2013/11/16 职场文书
应届毕业生应聘自荐信范文
2014/02/26 职场文书
党员入党表决心的话
2014/03/11 职场文书
化学教育专业自荐信
2014/07/04 职场文书
爱的承诺书
2015/01/20 职场文书
乡镇安全生产月活动总结
2015/05/08 职场文书
python实现网络五子棋
2021/04/11 Python
python四个坐标点对图片区域最小外接矩形进行裁剪
2021/06/04 Python
Winsows11性能如何? win11性能测评多核竟比Win10差了10%
2021/11/21 数码科技
一次线上mongo慢查询问题排查处理记录
2022/03/18 MongoDB