python with用法
@python with用法
?
python中with可以明顯改進(jìn)代碼友好度,比如:
[python] view plaincopyprint?
為了我們自己的類也可以使用with, 只要給這個(gè)類增加兩個(gè)函數(shù)__enter__, __exit__即可:
另外python庫中還有一個(gè)模塊contextlib,使你不用構(gòu)造含有__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 #實(shí)用 17 with context(): 18 print '----------in context call-------'結(jié)果:
entering the zone
----------in context call-------
with no error
使用的最多的就是這個(gè)contextmanager, 另外還有一個(gè)closing 用處不大
?
[python]自python? 2.6開始,成為默認(rèn)關(guān)鍵字。
在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是一個(gè)控制流語句,跟if/for/while/try之類的是一類的,with可以用來簡(jiǎn)化try finally代碼,看起來可以比try finally更清晰。
這里新引入了一個(gè)"上下文管理協(xié)議"context management protocol,實(shí)現(xiàn)方法是為一個(gè)類定義__enter__和__exit__兩個(gè)函數(shù)。
with expresion as variable的執(zhí)行過程是,首先執(zhí)行__enter__函數(shù),它的返回值會(huì)賦給as后面的variable,想讓它返回什么就返回什么,只要你知道怎么處理就可以了,如果不寫as variable,返回值會(huì)被忽略。
然后,開始執(zhí)行with-block中的語句,不論成功失敗(比如發(fā)生異常、錯(cuò)誤,設(shè)置sys.exit()),在with-block執(zhí)行完成后,會(huì)執(zhí)行__exit__函數(shù)。
這樣的過程其實(shí)等價(jià)于:
try:
執(zhí)行 __enter__的內(nèi)容
執(zhí)行 with_block.
finally:
執(zhí)行 __exit__內(nèi)容
只不過,現(xiàn)在把一部分代碼封裝成了__enter__函數(shù),清理代碼封裝成__exit__函數(shù)。
我們可以自己實(shí)現(xiàn)一個(gè)例子:
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__函數(shù)的返回值,這是with拿到test()的對(duì)象執(zhí)行之后的結(jié)果。t的值是1.
2,__exit__函數(shù)的返回值用來指示with-block部分發(fā)生的異常是否要re-raise,如果返回False,則會(huì)re-raise with-block的異常,如果返回True,則就像什么都沒發(fā)生。
符合這種特征的實(shí)現(xiàn)就是符合“上下文管理協(xié)議”了,就可以跟with聯(lián)合使用了。
as關(guān)鍵字的另一個(gè)用法是except XXX as e,而不是以前的except XXX,e的方式了。
此外,還可以使用contextlib模塊中的contextmanager,方法是:
@contextmanager
...
yield something
...
的方式,具體需要看看文檔和手冊(cè)了。
yield的用法還是很神奇的,一句兩句搞不清楚,如果您已經(jīng)弄懂,看看文檔就明白了,如果不懂yield,根據(jù)自己的需要去弄懂或者干脆不理他也可以,反正用到的時(shí)候,您一定回去搞懂的:-
其實(shí)with很像一個(gè)wrapper或者盒子,把with-block部分的代碼包裝起來,加一個(gè)頭,加一個(gè)尾,頭是__enter__,尾是__exit__,無論如何,頭尾都是始終要執(zhí)行的。
有一篇詳細(xì)的介紹在:http://effbot.org/zone/python-with-statement.htm
?
我簡(jiǎn)單翻譯一下其中的要點(diǎn):
如果有一個(gè)類包含? __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
? ? 當(dāng)with語句被執(zhí)行的時(shí)候,python對(duì)表達(dá)式進(jìn)行求值,對(duì)求值的結(jié)果(叫做“內(nèi)容守護(hù)者”)調(diào)用__enter__方法,并把__enter__
方法的返回值賦給as后面的變量。然后python會(huì)執(zhí)行接下來的代碼段,并且無論這段代碼干了什么,都會(huì)執(zhí)行“內(nèi)容守護(hù)者”的__exit__
方法。
?????? 作為額外的紅利,__exit__方法還能夠在有exception的時(shí)候看到exception,并且壓制它或者對(duì)它做出必要的反應(yīng)。要壓制 exception,只需要返回一個(gè)true。比如,下面的__exit__方法吞掉了任何的TypeError,但是讓所有其他的exceptions 通過:
def__exit__(self, type, value, traceback):return?isinstance(value, TypeError)
在Python2.5中,file object擁有__enter__和__exit__方法,前者僅僅是返回object自己,而后者則關(guān)閉這個(gè)文件:
>>> 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
這樣要打開一個(gè)文件,處理它的內(nèi)容,并且保證關(guān)閉它,你就可以簡(jiǎn)簡(jiǎn)單單地這樣做:
with?open("x.txt") as f:
data = f.read()
do something?with?data
轉(zhuǎn)載于:https://www.cnblogs.com/liunnis/p/4627739.html
總結(jié)
以上是生活随笔為你收集整理的python with用法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: avalon.js实践 svg地图配置工
- 下一篇: 【转】MySQL的语句执行顺序