python with用法
@python with用法
?
python中with可以明顯改進代碼友好度,比如:
[python] view plaincopyprint?
為了我們自己的類也可以使用with, 只要給這個類增加兩個函數__enter__, __exit__即可:
另外python庫中還有一個模塊contextlib,使你不用構造含有__enter__, __exit__的類就可以使用with:
?
1 #-*- coding:utf-8 -*- 2 from __future__ import with_statement 3 from contextlib import contextmanager 4 5 @contextmanager 6 def context(): 7 print 'entering the zone' 8 try: 9 yield 10 except Exception,e: 11 print 'with an error %s ..' % e 12 raise e 13 else: 14 print 'with no error' 15 16 #實用 17 with context(): 18 print '----------in context call-------'結果:
entering the zone
----------in context call-------
with no error
使用的最多的就是這個contextmanager, 另外還有一個closing 用處不大
?
[python]自python? 2.6開始,成為默認關鍵字。
在What's new in python2.6/3.0中,明確提到:
The 'with'?statement is a control-flow structure whose basic?structure is:
with expression [as variable]:?with-block
也就是說with是一個控制流語句,跟if/for/while/try之類的是一類的,with可以用來簡化try finally代碼,看起來可以比try finally更清晰。
這里新引入了一個"上下文管理協議"context management protocol,實現方法是為一個類定義__enter__和__exit__兩個函數。
with expresion as variable的執行過程是,首先執行__enter__函數,它的返回值會賦給as后面的variable,想讓它返回什么就返回什么,只要你知道怎么處理就可以了,如果不寫as variable,返回值會被忽略。
然后,開始執行with-block中的語句,不論成功失敗(比如發生異常、錯誤,設置sys.exit()),在with-block執行完成后,會執行__exit__函數。
這樣的過程其實等價于:
try:
執行 __enter__的內容
執行 with_block.
finally:
執行 __exit__內容
只不過,現在把一部分代碼封裝成了__enter__函數,清理代碼封裝成__exit__函數。
我們可以自己實現一個例子:
import sys
class test:
def __enter__(self):
?? ??? print("enter")
?? ??? return 1
def __exit__(self,*args):
?? ??? print("exit")
?? ??? return True
with test() as t:
print("t is not the result of test(), it is __enter__ returned")
print("t is 1, yes, it is {0}".format(t))
raise NameError("Hi there")
sys.exit()
print("Never here")
注意:
1,t不是test()的值,test()返回的是"context manager object",是給with用的。t獲得的是__enter__函數的返回值,這是with拿到test()的對象執行之后的結果。t的值是1.
2,__exit__函數的返回值用來指示with-block部分發生的異常是否要re-raise,如果返回False,則會re-raise with-block的異常,如果返回True,則就像什么都沒發生。
符合這種特征的實現就是符合“上下文管理協議”了,就可以跟with聯合使用了。
as關鍵字的另一個用法是except XXX as e,而不是以前的except XXX,e的方式了。
此外,還可以使用contextlib模塊中的contextmanager,方法是:
@contextmanager
...
yield something
...
的方式,具體需要看看文檔和手冊了。
yield的用法還是很神奇的,一句兩句搞不清楚,如果您已經弄懂,看看文檔就明白了,如果不懂yield,根據自己的需要去弄懂或者干脆不理他也可以,反正用到的時候,您一定回去搞懂的:-
其實with很像一個wrapper或者盒子,把with-block部分的代碼包裝起來,加一個頭,加一個尾,頭是__enter__,尾是__exit__,無論如何,頭尾都是始終要執行的。
有一篇詳細的介紹在:http://effbot.org/zone/python-with-statement.htm
?
我簡單翻譯一下其中的要點:
如果有一個類包含? __enter__ 方法和 __exit__ 方法,像這樣:
class? controlled_execution:
?????? def__enter__(self):
????????????? set things up
????????????? return?thing
??????? def__exit__(self, type, value, traceback):
????????????? tear things down
那么它就可以和with一起使用,像這樣:
some code
? ? 當with語句被執行的時候,python對表達式進行求值,對求值的結果(叫做“內容守護者”)調用__enter__方法,并把__enter__
方法的返回值賦給as后面的變量。然后python會執行接下來的代碼段,并且無論這段代碼干了什么,都會執行“內容守護者”的__exit__
方法。
?????? 作為額外的紅利,__exit__方法還能夠在有exception的時候看到exception,并且壓制它或者對它做出必要的反應。要壓制 exception,只需要返回一個true。比如,下面的__exit__方法吞掉了任何的TypeError,但是讓所有其他的exceptions 通過:
def__exit__(self, type, value, traceback):return?isinstance(value, TypeError)
在Python2.5中,file object擁有__enter__和__exit__方法,前者僅僅是返回object自己,而后者則關閉這個文件:
>>> f = open("x.txt")
>>> f
<open file?'x.txt', mode?'r'?at 0x00AE82F0>
>>> f.__enter__()
<open file?'x.txt', mode?'r'?at 0x00AE82F0>
>>> f.read(1)
'X'
>>> f.__exit__(None, None, None)
>>> f.read(1)
Traceback (most recent call last):
File?"<stdin>", line 1,?in?<module>
ValueError: I/O operation on closed file
這樣要打開一個文件,處理它的內容,并且保證關閉它,你就可以簡簡單單地這樣做:
with?open("x.txt") as f:
data = f.read()
do something?with?data
轉載于:https://www.cnblogs.com/liunnis/p/4627739.html
總結
以上是生活随笔為你收集整理的python with用法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: avalon.js实践 svg地图配置工
- 下一篇: python学习笔记(字典)