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 相关文章推荐
Python3基础之基本运算符概述
Aug 13 Python
简单介绍Python中的try和finally和with方法
May 05 Python
使用Python对SQLite数据库操作
Apr 06 Python
python数据结构之链表的实例讲解
Jul 25 Python
微信跳一跳python代码实现
Jan 05 Python
Python cookbook(数据结构与算法)实现对不原生支持比较操作的对象排序算法示例
Mar 15 Python
浅谈django rest jwt vue 跨域问题
Oct 26 Python
Python中collections模块的基本使用教程
Dec 07 Python
详解Python中pandas的安装操作说明(傻瓜版)
Apr 08 Python
树莓派+摄像头实现对移动物体的检测
Jun 22 Python
python3.x 生成3维随机数组实例
Nov 28 Python
Python实现ATM系统
Feb 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
php数组对百万数据进行排除重复数据的实现代码
2010/06/08 PHP
解析PHP中VC6 X86和VC9 X86的区别及 Non Thread Safe的意思
2013/06/28 PHP
PHP设计模式之观察者模式定义与用法示例
2018/08/04 PHP
Laravel服务容器绑定的几种方法总结
2020/06/14 PHP
URL编码转换,escape() encodeURI() encodeURIComponent()
2006/12/27 Javascript
javascript 强制刷新页面的实现代码
2009/12/13 Javascript
基于jquery的无刷新分页技术
2011/06/11 Javascript
基于javascipt-dom编程 table对象的使用
2013/04/22 Javascript
javascript弹出层输入框(示例代码)
2013/12/11 Javascript
遮罩层点击按钮弹出并且具有拖动和关闭效果(两种方法)
2015/08/20 Javascript
vue.js 获取当前自定义属性值
2017/06/01 Javascript
js实现弹出框的拖拽效果实例代码详解
2019/04/16 Javascript
JS匿名函数内部this指向问题详析
2019/05/10 Javascript
js实现倒计时秒杀效果
2020/03/25 Javascript
一篇文章带你使用Typescript封装一个Vue组件(简单易懂)
2020/06/05 Javascript
Python标准库之循环器(itertools)介绍
2014/11/25 Python
Sanic框架安装与简单入门示例
2018/07/16 Python
python提取log文件内容并画出图表
2019/07/08 Python
解决pytorch GPU 计算过程中出现内存耗尽的问题
2019/08/19 Python
Python matplotlib修改默认字体的操作
2020/03/05 Python
浅谈Python中的继承
2020/06/19 Python
Pytorch实现WGAN用于动漫头像生成
2021/03/04 Python
CAT鞋美国官网:CAT Footwear
2017/11/27 全球购物
斯巴达比赛商店:Spartan Race
2019/01/08 全球购物
2014年会演讲稿范文
2014/01/06 职场文书
英语简历自我评价
2014/01/26 职场文书
事假请假条范文
2014/04/11 职场文书
网络销售员岗位职责
2015/04/11 职场文书
社区青年志愿者活动总结
2015/05/06 职场文书
退休欢送会致辞
2015/07/31 职场文书
小学六年级班主任工作经验交流材料
2015/11/02 职场文书
Nginx服务器如何设置url链接
2021/03/31 Servers
canvas实现贪食蛇的实践
2022/02/15 Javascript
使用python求解迷宫问题的三种实现方法
2022/03/17 Python
GPU服务器的多用户配置方法
2022/07/07 Servers
Spring Boot优化后启动速度快到飞起技巧示例
2022/07/23 Java/Android