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基础入门学习笔记(Python环境搭建)
Jan 13 Python
Django URL传递参数的方法总结
Aug 28 Python
Python自定义类的数组排序实现代码
Aug 28 Python
Python内置函数OCT详解
Nov 09 Python
python进阶_浅谈面向对象进阶
Aug 17 Python
PyQt5实现下载进度条效果
Apr 19 Python
关于python2 csv写入空白行的问题
Jun 22 Python
Python 加密与解密小结
Dec 06 Python
python3实现高效的端口扫描
Aug 31 Python
python实现逆滤波与维纳滤波示例
Feb 26 Python
python GUI库图形界面开发之PyQt5下拉列表框控件QComboBox详细使用方法与实例
Feb 27 Python
使用 Python 遍历目录树的方法
Feb 29 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脚本中include文件出错解决方法
2008/11/20 PHP
Laravel框架中扩展函数、扩展自定义类的方法
2014/09/04 PHP
symfony表单与页面实现技巧
2015/01/26 PHP
PHP基于回溯算法解决n皇后问题的方法示例
2017/11/07 PHP
PHP实现关键字搜索后描红功能示例
2019/07/03 PHP
js可突破windows弹退效果代码
2008/08/09 Javascript
jQuery :nth-child前有无空格的区别分析
2011/07/11 Javascript
Node.js(安装,启动,测试)
2014/06/09 Javascript
基于JavaScript代码实现兼容各浏览器的设为首页和加入收藏
2016/01/07 Javascript
jQuery设置和获取select、checkbox、radio的选中值方法
2017/01/01 Javascript
jQuery插件FusionWidgets实现的Cylinder图效果示例【附demo源码】
2017/03/23 jQuery
Vue基于NUXT的SSR详解
2017/10/24 Javascript
React 无状态组件(Stateless Component) 与高阶组件
2018/08/14 Javascript
vue 实现边输入边搜索功能的实例讲解
2018/09/16 Javascript
手动下载Chrome并解决puppeteer无法使用问题
2018/11/12 Javascript
JavaScript算法学习之冒泡排序和选择排序
2019/11/02 Javascript
NestJs使用Mongoose对MongoDB操作的方法
2021/02/22 Javascript
[01:11:35]Liquid vs LGD 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
Python 调用VC++的动态链接库(DLL)
2008/09/06 Python
Python发送Email方法实例
2014/08/21 Python
Python读写及备份oracle数据库操作示例
2018/05/17 Python
Python线上环境使用日志的及配置文件
2019/07/28 Python
python如何求圆的面积
2020/07/01 Python
python 实现"神经衰弱"翻牌游戏
2020/11/09 Python
Canvas 文本填充线性渐变的使用详解
2020/06/22 HTML / CSS
HTML5 SEO优化的一些建议
2020/08/27 HTML / CSS
什么是三层交换,说说和路由的区别在那里
2014/09/01 面试题
网上蛋糕店创业计划书
2014/01/24 职场文书
党员群众路线承诺书
2014/05/20 职场文书
民政局副局长民主生活会个人整改措施
2014/10/04 职场文书
肖申克的救赎观后感
2015/06/02 职场文书
祝福语集锦:送给闺蜜的生日祝福语
2019/10/08 职场文书
《学会生存》读后感3篇
2019/12/09 职场文书
详解Apache SkyWalking 告警配置指南
2021/04/22 Servers
php中配置文件保存修改操作 如config.php文件的读取修改等操作
2021/05/12 PHP
Sql Server 行数据的某列值想作为字段列显示的方法
2022/04/20 SQL Server