Python积木之with
简而言之,with 语句是典型的程序块 “try catch finally”的一种模式抽取。python的作者在PEP343中写道
“ This PEP adds a new statement "with" to the Python language to make it possible to factor out standard uses of try/finally statements.”
这是Python追求语言简化做出的一种语法糖。
with 可以作用于类的某个方法,但是这个类必须实现__enter__和 __exit__两个方法。调用类的某个方法时,首先会调用__enter__方法,再调用方法本身,最后调用__exit__方法。
例如下面代码:
with file(r'D:\a.txt','r') as f : print f.read()
这样,我们实现了读取a.txt所有内容。读取后又关闭了文件。
我们可以查看file方法所在的__builtin_模块,你可以搜索对应file类到__enter__和__exit__的方法(这个例子不好,因为file是c实现的,这里只有壳,但能帮助你明白是什么意思)
下面出自python的官方文档,详细说明了with的用法。with还支持嵌套。
with_stmt ::= "with" with_item ("," with_item)* ":" suite with_item ::= expression ["as" target]
-
The context expression (the expression given in the with_item) is evaluated to obtain a context manager.
-
The context manager’s __exit__() is loaded for later use.
-
The context manager’s __enter__() method is invoked.
-
If a target was included in the with statement, the return value from __enter__() is assigned to it.
Note
The with statement guarantees that if the __enter__() method returns without an error, then __exit__() will always be called. Thus, if an error occurs during the assignment to the target list, it will be treated the same as an error occurring within the suite would be. See step 6 below.
-
The suite is executed.
-
The context manager’s __exit__() method is invoked. If an exception caused the suite to be exited, its type, value, and traceback are passed as arguments to __exit__(). Otherwise, three Nonearguments are supplied.
If the suite was exited due to an exception, and the return value from the __exit__() method was false, the exception is reraised. If the return value was true, the exception is suppressed, and execution continues with the statement following the with statement.
If the suite was exited for any reason other than an exception, the return value from __exit__() is ignored, and execution proceeds at the normal location for the kind of exit that was taken.
With more than one item, the context managers are processed as if multiple with statements were nested:
with A() as a, B() as b:
suite
is equivalent to
with A() as a:
with B() as b:
suite