自定义可以和with一起工作的类

with语句在很多情况下都很有用,使用它可以大大简化代码。

例如我们想要读取一个文件:

1 with open(‘test.txt’, ‘r’) as f:
2     for l in f :
3         print l

 

with语句执行完之后,f对象的close成员函数会被自动调用。

 

天下没有免费的午餐,你想使用with语句,想知道什么时候能使用它,还需要了解这样一个事实:with语句仅能工作于支持上下文管理协议(context management protocol)的对象

 

常见的支持上下文管理协议的对象有:file, threading模块中的locks, conditions,semaphores等。

关于上下文管理协议

紧跟在with关键字之后的表达式,应该返回一个对象,我们把这个对象称为上下文对象,这个对象需要有一个__enter__()方法和一个__exit__()方法。

 

在进入with语句块之前,python会调用上下文对象的__enter__()方法,它将完成with语句执行前的所有初始化工作。注意到with语句有一个可选的as var语句,它用以保存上下文对象。如果使用了as语句,则以__enter__()的返回值,为紧跟在as 之后的变量赋值

 

with结束时,无论它是否是正常结束,都会调用上下文对象的__exit__()方法。

__exit__()有三个参数,如果with语句没有发生异常,则此三个参数全部为None;若发生异常,这三个参数分别等于调用sys.exc_info()函数的三个返回值:异常类型,异常实例,跟踪记录(traceback)如果想屏蔽发生的异常,那么设置__exit__()的返回值为True

 

下面我们看一个简单的例子:

有一个consolecolor模块可以设置控制台的颜色,我想要实现这样的效果,使用某种颜色输出字符串后,立刻恢复到先前的颜色,于是我定义了这样一个类:

 1 def color(color):  # 一个帮助函数
 2     return ConsoleColor(color)
 3  
 4 class ConsoleColor(object):
 5     def __init__(self, color):
 6         self.color = color
 7     def __enter__(self):
 8         self.oldcolor = consolecolor.get_color()
 9         consolecolor.set_color(self.color)
10     def __exit__(self, e, v, tb):
11         consolecolor.set_color(self.oldcolor)

 

运行效果如下:


 

posted on 2012-10-19 17:38  sanlo  阅读(283)  评论(0编辑  收藏  举报