with语法

with语句实质上是上下文管理,是try...finally...的简化

 1 try:
 2     f = open('/path/to/file', 'r')
 3     f.read()
 4 finally:
 5     if f:
 6         f.close()
 7         
 8 --------------------------------------
 9 10 with open('/path/to/file', 'r') as f:
11     f.read()

任何对象,只要正确使用了上下文管理器,就可以使使用with

实现上下文管理只要定义__enter____exit__即可

 1 class Query(object):
 2     def __init__(self, name):
 3         self.name = name
 4  5     def __enter__(self):
 6         print('I entered')
 7         return self 
 8     
 9     def __exit__(self, exc_type, exc_value, traceback):
10         if exc_type:
11             print('Error')
12         else:
13             print('End')
14     
15     def query(self):
16         print('Query info about %s...' % self.name)

在调用构造之前调用__enter__,在执行完with里面的代码块之后调用__exit__

使用:with 构造对象 as 对象变量名

1 with Query('Martin') as q:
2     q.query()

编写__enter____exit__仍然很繁琐,因此Python的标准库contextlib提供了更简单的写法,上面的代码可以改写如下:

 1 from contextlib import contextmanager
 2  3 class Query(object):
 4     def __init__(self, name):
 5         self.name = name
 6  7     def query(self):
 8         print('Query info about %s...' % self.name)
 9 10 11 @contextmanager
12 def create_query(name):
13     print('Begin')
14     q = Query(name)
15     yield q
16     print('End')

使用:with 其他函数 as 对象变量名:

1 with create_query('Bob') as q:
2     q.query()

执行顺序:

  1. 打印”Begin“,初始化一个q对象

  2. q对象返回到with,即 as q

  3. 执行q.query()

  4. 打印"End"