欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

Python的with語句如何使用

這篇文章主要講解了“Python的with語句如何使用”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Python的with語句如何使用”吧!

成都創(chuàng)新互聯(lián)主營(yíng)石阡網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,App定制開發(fā),石阡h5微信小程序搭建,石阡網(wǎng)站營(yíng)銷推廣歡迎石阡等地區(qū)企業(yè)咨詢

語句體(with-body):with 語句包裹起來的代碼塊,在執(zhí)行語句體之前會(huì)調(diào)用上下文管理器的 enter() 方法,執(zhí)行完語句體之后會(huì)執(zhí)行 exit() 方法。

基本語法和工作原理

with 語句的語法格式如下:

清單 1. with 語句的語法格式

with context_expression [as target(s)]:

with-body

這里 contextexpression 要返回一個(gè)上下文管理器對(duì)象,該對(duì)象并不賦值給 as 子句中的 target(s) ,如果指定了 as 子句的話,會(huì)將上下文管理器的 _enter() 方法的返回值賦值給 target(s)。target(s) 可以是單個(gè)變量,或者由“()”括起來的元組(不能是僅僅由“,”分隔的變量列表,必須加“()”)。

Python 對(duì)一些內(nèi)建對(duì)象進(jìn)行改進(jìn),加入了對(duì)上下文管理器的支持,可以用于 with 語句中,比如可以自動(dòng)關(guān)閉文件、線程鎖的自動(dòng)獲取和釋放等。假設(shè)要對(duì)一個(gè)文件進(jìn)行操作,使用 with 語句可以有如下代碼:

清單 2. 使用 with 語句操作文件對(duì)象

with open(r'somefileName') as somefile:

for line in somefile:

print line

# ...more code

這里使用了 with 語句,不管在處理文件過程中是否發(fā)生異常,都能保證 with 語句執(zhí)行完畢后已經(jīng)關(guān)閉了打開的文件句柄。如果使用傳統(tǒng)的 try/finally 范式,則要使用類似如下代碼:

清單 3. try/finally 方式操作文件對(duì)象

somefile = open(r'somefileName')

try:

for line in somefile:

print line

# ...more code

finally:

somefile.close()

比較起來,使用 with 語句可以減少編碼量。已經(jīng)加入對(duì)上下文管理協(xié)議支持的還有模塊 threading、decimal 等。

PEP 0343 對(duì) with 語句的實(shí)現(xiàn)進(jìn)行了描述。with 語句的執(zhí)行過程類似如下代碼塊:

清單 4. with 語句執(zhí)行過程

context_manager = context_expression

exit = type(context_manager).__exit__

value = type(context_manager).__enter__(context_manager)

exc = True # True 表示正常執(zhí)行,即便有異常也忽略;False 表示重新拋出異常,需要對(duì)異常進(jìn)行處理

try:

try:

target = value # 如果使用了 as 子句

with-body # 執(zhí)行 with-body

except: # 執(zhí)行過程中有異常發(fā)生

exc = False

# 如果 __exit__ 返回 True,則異常被忽略;如果返回 False,則重新拋出異常

# 由外層代碼對(duì)異常進(jìn)行處理

if not exit(context_manager, *sys.exc_info()):

raise

finally:

# 正常退出,或者通過 statement-body 中的 break/continue/return 語句退出

# 或者忽略異常退出

if exc:

exit(context_manager, None, None, None)

# 缺省返回 None,None 在布爾上下文中看做是 False

執(zhí)行 context_expression,生成上下文管理器 context_manager。

調(diào)用上下文管理器的 enter() 方法;如果使用了 as 子句,則將 enter() 方法的返回值賦值給 as 子句中的 target(s)。

執(zhí)行語句體 with-body

不管是否執(zhí)行過程中是否發(fā)生了異常,執(zhí)行上下文管理器的 exit() 方法,exit() 方法負(fù)責(zé)執(zhí)行“清理”工作,如釋放資源等。如果執(zhí)行過程中沒有出現(xiàn)異常,或者語句體中執(zhí)行了語句 break/continue/return,則以 None 作為參數(shù)調(diào)用 exit(None, None, None) ;如果執(zhí)行過程中出現(xiàn)異常,則使用 sys.excinfo 得到的異常信息為參數(shù)調(diào)用 _exit(exc_type, exc_value, exc_traceback)。

出現(xiàn)異常時(shí),如果 exit(type, value, traceback) 返回 False,則會(huì)重新拋出異常,讓with 之外的語句邏輯來處理異常,這也是通用做法;如果返回 True,則忽略異常,不再對(duì)異常進(jìn)行處理。

自定義上下文管理器

開發(fā)人員可以自定義支持上下文管理協(xié)議的類。自定義的上下文管理器要實(shí)現(xiàn)上下文管理協(xié)議所需要的 enter() 和 exit() 兩個(gè)方法:

contextmanager._enter() :進(jìn)入上下文管理器的運(yùn)行時(shí)上下文,在語句體執(zhí)行前調(diào)用。with 語句將該方法的返回值賦值給 as 子句中的 target,如果指定了 as 子句的話。

contextmanager._exit(exc_type, exc_value, exc_traceback) :退出與上下文管理器相關(guān)的運(yùn)行時(shí)上下文,返回一個(gè)布爾值表示是否對(duì)發(fā)生的異常進(jìn)行處理。參數(shù)表示引起退出操作的異常,如果退出時(shí)沒有發(fā)生異常,則3個(gè)參數(shù)都為None。如果發(fā)生異常,返回。

True 表示不處理異常,否則會(huì)在退出該方法后重新拋出異常以由 with 語句之外的代碼邏輯進(jìn)行處理。如果該方法內(nèi)部產(chǎn)生異常,則會(huì)取代由 statement-body中語句產(chǎn)生的異常。要處理異常時(shí),不要顯示重新拋出異常,即不能重新拋出通過參數(shù)傳遞進(jìn)來的異常,只需要將返回值設(shè)置為 False 就可以了。之后,上下文管理代碼會(huì)檢測(cè)是否 exit() 失敗來處理異常。

下面通過一個(gè)簡(jiǎn)單的示例來演示如何構(gòu)建自定義的上下文管理器。注意,上下文管理器必須同時(shí)提供 enter() 和 exit() 方法的定義,缺少任何一個(gè)都會(huì)導(dǎo)致 AttributeError;with 語句會(huì)先檢查是否提供了 exit() 方法,然后檢查是否定義了 enter() 方法。

假設(shè)有一個(gè)資源 DummyResource,這種資源需要在訪問前先分配,使用完后再釋放掉;分配操作可以放到 enter() 方法中,釋放操作可以放到 exit() 方法中。簡(jiǎn)單起見,這里只通過打印語句來表明當(dāng)前的操作,并沒有實(shí)際的資源分配與釋放。

清單 5. 自定義支持 with 語句的對(duì)象

class DummyResource:

def __init__(self, tag):

self.tag = tag

print 'Resource [%s]' % tag

def __enter__(self):

print '[Enter %s]: Allocate resource.' % self.tag

return self # 可以返回不同的對(duì)象

def __exit__(self, exc_type, exc_value, exc_tb):

print '[Exit %s]: Free resource.' % self.tag

if exc_tb is None:

print '[Exit %s]: Exited without exception.' % self.tag

else:

print '[Exit %s]: Exited with exception raised.' % self.tag

return False # 可以省略,缺省的None也是被看做是False

DummyResource 中的 enter() 返回的是自身的引用,這個(gè)引用可以賦值給 as 子句中的 target 變量;返回值的類型可以根據(jù)實(shí)際需要設(shè)置為不同的類型,不必是上下文管理器對(duì)象本身。

exit() 方法中對(duì)變量 exctb 進(jìn)行檢測(cè),如果不為 None,表示發(fā)生了異常,返回 False 表示需要由外部代碼邏輯對(duì)異常進(jìn)行處理;注意到如果沒有發(fā)生異常,缺省的返回值為 None,在布爾環(huán)境中也是被看做 False,但是由于沒有異常發(fā)生,_exit() 的三個(gè)參數(shù)都為 None,上下文管理代碼可以檢測(cè)這種情況,做正常處理。

下面在 with 語句中訪問 DummyResource :

清單 6. 使用自定義的支持 with 語句的對(duì)象

with DummyResource('Normal'):

print '[with-body] Run without exceptions.'

with DummyResource('With-Exception'):

print '[with-body] Run with exception.'

raise Exception

print '[with-body] Run with exception. Failed to finish statement-body!'

第1個(gè) with 語句的執(zhí)行結(jié)果如下:

清單 7. with 語句1執(zhí)行結(jié)果

Resource [Normal]

[Enter Normal]: Allocate resource.

[with-body] Run without exceptions.

[Exit Normal]: Free resource.

[Exit Normal]: Exited without exception.

可以看到,正常執(zhí)行時(shí)會(huì)先執(zhí)行完語句體 with-body,然后執(zhí)行 exit() 方法釋放資源。

第2個(gè) with 語句的執(zhí)行結(jié)果如下:

清單 8. with 語句2執(zhí)行結(jié)果

Resource [With-Exception]

[Enter With-Exception]: Allocate resource.

[with-body] Run with exception.

[Exit With-Exception]: Free resource.

[Exit With-Exception]: Exited with exception raised.

Traceback (most recent call last):

File "G:/demo", line 20, in raise Exception

Exception

可以看到,with-body 中發(fā)生異常時(shí)with-body 并沒有執(zhí)行完,但資源會(huì)保證被釋放掉,同時(shí)產(chǎn)生的異常由 with 語句之外的代碼邏輯來捕獲處理。

可以自定義上下文管理器來對(duì)軟件系統(tǒng)中的資源進(jìn)行管理,比如數(shù)據(jù)庫連接、共享資源的訪問控制等。Python 在線文檔 Writing Context Managers 提供了一個(gè)針對(duì)數(shù)據(jù)庫連接進(jìn)行管理的上下文管理器的簡(jiǎn)單范例。

contextlib 模塊

contextlib 模塊提供了3個(gè)對(duì)象:裝飾器 contextmanager、函數(shù)nested和上下文管理器closing。使用這些對(duì)象,可以對(duì)已有的生成器函數(shù)或者對(duì)象進(jìn)行包裝,加入對(duì)上下文管理協(xié)議的支持,避免了專門編寫上下文管理器來支持 with 語句。

裝飾器 contextmanager

contextmanager 用于對(duì)生成器函數(shù)進(jìn)行裝飾,生成器函數(shù)被裝飾以后,返回的是一個(gè)上下文管理器,其 enter() 和 exit() 方法由 contextmanager 負(fù)責(zé)提供,而不再是之前的迭代子。被裝飾的生成器函數(shù)只能產(chǎn)生一個(gè)值,否則會(huì)導(dǎo)致異常 RuntimeError;產(chǎn)生的值會(huì)賦值給 as 子句中的 target,如果使用了 as 子句的話。下面看一個(gè)簡(jiǎn)單的例子。

清單 9. 裝飾器 contextmanager 使用示例

from contextlib import contextmanager

@contextmanager

def demo():

print '[Allocate resources]'

print 'Code before yield-statement executes in __enter__'

yield '*** contextmanager demo ***'

print 'Code after yield-statement executes in __exit__'

print '[Free resources]'

with demo() as value:

print 'Assigned Value: %s' % value

結(jié)果輸出如下:

清單 10. contextmanager 使用示例執(zhí)行結(jié)果

[Allocate resources]

Code before yield-statement executes in __enter__

Assigned Value: *** contextmanager demo ***

Code after yield-statement executes in __exit__

[Free resources]

可以看到,生成器函數(shù)中 yield 之前的語句在 enter() 方法中執(zhí)行,yield 之后的語句在 exit() 中執(zhí)行,而 yield 產(chǎn)生的值賦給了 as 子句中的 value 變量。

需要注意的是,contextmanager 只是省略了 enter() / exit() 的編寫,但并不負(fù)責(zé)實(shí)現(xiàn)資源的“獲取”和“清理”工作;“獲取”操作需要定義在 yield 語句之前,“清理”操作需要定義 yield 語句之后,這樣 with 語句在執(zhí)行 enter() / exit() 方法時(shí)會(huì)執(zhí)行這些語句以獲取/釋放資源,即生成器函數(shù)中需要實(shí)現(xiàn)必要的邏輯控制,包括資源訪問出現(xiàn)錯(cuò)誤時(shí)拋出適當(dāng)?shù)漠惓!?/p>

函數(shù) nested

nested 可以將多個(gè)上下文管理器組織在一起,避免使用嵌套 with 語句。

清單 11. nested 語法

with nested(A(), B(), C()) as (X, Y, Z):

# with-body code here

類似于:

清單 12. nested 執(zhí)行過程

with A() as X:

with B() as Y:

with C() as Z:

# with-body code here

需要注意的是,發(fā)生異常后,如果某個(gè)上下文管理器的 exit() 方法對(duì)異常處理返回 False,則更外層的上下文管理器不會(huì)監(jiān)測(cè)到異常。

上下文管理器 closing

closing 的實(shí)現(xiàn)如下:

清單 13. 上下文管理 closing 實(shí)現(xiàn)

class closing(object):

# help doc here

def __init__(self, thing):

self.thing = thing

def __enter__(self):

return self.thing

def __exit__(self, *exc_info):

self.thing.close()

上下文管理器會(huì)將包裝的對(duì)象賦值給 as 子句的 target 變量,同時(shí)保證打開的對(duì)象在 with-body 執(zhí)行完后會(huì)關(guān)閉掉。closing 上下文管理器包裝起來的對(duì)象必須提供 close() 方法的定義,否則執(zhí)行時(shí)會(huì)報(bào) AttributeError 錯(cuò)誤。

清單 14. 自定義支持 closing 的對(duì)象

class ClosingDemo(object):

def __init__(self):

self.acquire()

def acquire(self):

print 'Acquire resources.'

def free(self):

print 'Clean up any resources acquired.'

def close(self):

self.free()

with closing(ClosingDemo()):

print 'Using resources'

結(jié)果輸出如下:

清單 15. 自定義 closing 對(duì)象的輸出結(jié)果

Acquire resources.

Using resources

Clean up any resources acquired.

closing 適用于提供了 close() 實(shí)現(xiàn)的對(duì)象,比如網(wǎng)絡(luò)連接、數(shù)據(jù)庫連接等,也可以在自定義類時(shí)通過接口 close() 來執(zhí)行所需要的資源“清理”工作。

感謝各位的閱讀,以上就是“Python的with語句如何使用”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)Python的with語句如何使用這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

新聞名稱:Python的with語句如何使用
文章轉(zhuǎn)載:http://aaarwkj.com/article16/peeodg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站、自適應(yīng)網(wǎng)站、網(wǎng)站設(shè)計(jì)公司網(wǎng)頁設(shè)計(jì)公司、響應(yīng)式網(wǎng)站搜索引擎優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

微信小程序開發(fā)
国产欧美日韩一二三四| 亚洲国产精品区一区二区| 日本又色又爽又黄又高潮| 国产怡红院在线视频观看| 国产精品高清另类一区二区三区| 国产男女猛进猛出精品91| 丝袜美腿亚洲欧美日韩| 五月婷婷亚洲激情综合网| 国产在线不卡免费精品| 国产特级黄片免费观看| 免费成人自拍偷拍视频| 亚洲精品隔壁傲慢人妻| 91国产在线视频免费观看| 国产大学生吞精在线视频| 少妇被按摩高潮在线观看| 人妻操人人妻中出av| 日韩在线视频一区二区三| 日韩精品一区伦理视频| 91精品麻豆国产自产在线| 一区二区三区四区四虎| 精品人妻av中文字幕| 久久精品色妇熟妇丰满人妻| 99精品一二三日韩| 亚洲精品亚洲一区亚洲二区| 日韩一二三区欧美四五区新| 免费精品黑人一区二区三区| 97青青草免费在线视频| 激情偷拍一区二区三区视频| 国产精品欧美久久久久久| 天天天干夜夜添狠操美女| 欧美一区二区三区人妻熟妇| 欧美色视频综合在线观看 | 五月婷婷综合中文字幕在线| 手机在线看国产后入| 婷婷中文字幕在线不卡视频| 国产精品国产一级国产av| 在线观看午夜视频免费| 亚洲福利一区二区在线| 国内一级黄色片免费观看| 亚洲午夜福利天堂社区| 欧美精品一区二区毛卡片|