python的with语法

python学习笔记之with语法

with语句与__enter__,exit

有一些任务,可能事先需要设置,事后做清理工作。对于这种场景,Python的with语句提供了一种非常方便的处理方式。一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。

如果不使用with语句,代码是这样的:

1
2
3
file = open("/tmp/foo.txt")
data = file.read()
file.close()

这里有两个问题。一是可能忘记关闭文件句柄;二是文件读取数据发生异常,没有进行任何处理。下面是处理异常的加强版本:

1
2
3
4
5
file = open("/tmp/foo.txt")
try:
data = file.read()
finally:
file.close()

虽然这段代码运行良好,但是太冗长了。这时候就是with一展身手的时候了。除了有更优雅的语法,with还可以很好的处理上下文环境产生的异常。下面是with版本的代码:

1
2
with open("/tmp/foo.txt") as file:
data = file.read()

那with语法是怎么实现的呢?下边来看一个类:

1
2
3
4
5
6
7
8
9
10
11
class Resource:
def __init__(self):
print("call __init__")

def __enter__(self):
print("call __enter__")
print("self object at {0}".format(self))
return self

def __exit__(self,*args,**kwargs):
print("call __exit__")
1
2
with Resource() as res:
print("res object at {0}".format(res))
call __init__
call __enter__
self object at <__main__.Resource object at 0x7f5db448a6a0>
res object at <__main__.Resource object at 0x7f5db448a6a0>
call __exit__

这上边这个例子可知,只要一个类实现了__enter____exit__方法,那这个类就可以使用with语句。

with语句的调用流程大致如下:

  1. python解释器执行到with Resource() as res:语句时,其实是首先实例化了Resource类,接着执行了__enter__函数

  2. 执行print("res object at {0}".format(res))语句,这里的res是指向Resource类实例化对象,所以与self指向的对象相同

  3. 再执行__exit__函数

1

1

1

1

文章目录
  1. 1. with语句与__enter__,exit
|