上下文管理器對象存在的目的就是管理with語句。上下文管理器協(xié)議包含__enter__ 和__exit__ 兩個方法。with 語句開始運(yùn)行時,會在上下文管理器對象上調(diào)用__enter__ 方法。with 語句運(yùn)行結(jié)束后,會在上下文管理器對象上調(diào)用__exit__ 方法
來看一個例子,把文件對象當(dāng)成上下文管理器使用
with
open
(
'test.dat'
)
as
fp
:
secc
=
fp
.
read
(
20
)
>>
>
len
(
src
)
20
>>
>
fp
<
_io
.
TextIOWrapper name
=
'mirror.py'
mode
=
'r'
encoding
=
'UTF-8'
>
>>
>
fp
.
closed
,
fp
.
encoding
(
True
,
'UTF-8'
)
"""
但是不能在fp 上執(zhí)行I/O 操作,因?yàn)樵趙ith 塊的末尾,調(diào)用TextIOWrapper.__exit__
方法把文件關(guān)閉了。
"""
>>
>
fp
.
read
(
60
)
Traceback
(
most recent call last
)
:
File
"
"
,
line
1
,
in
<
module
>
ValueError
:
I
/
O operation on closed
file
.
執(zhí)行with后面的表達(dá)式得到的結(jié)果是上下文管理器對象,不過,把值綁定到目標(biāo)變量上(as子句)是上下文管理器調(diào)用__enter__方法的結(jié)果
來看一個例子,自己實(shí)現(xiàn)一個上下文管理器
class
Sample
(
)
:
def
__enter__
(
self
)
:
print
(
"in __enter__"
)
return
self
def
__exit__
(
self
,
exc_type
,
exc_val
,
exc_tb
)
:
print
(
"in __exit__"
)
def
do_something
(
self
)
:
print
(
"i am doing something"
)
>>
>
with
Sample
(
)
as
sample
:
sample
.
do_something
(
)
in
__enter__
i am doing something
in
__exit__
真?zhèn)€過程運(yùn)行如下,enter()方法被執(zhí)行,enter()方法返回值,在這里是類自身,執(zhí)行代碼塊sample.do_something(), 最后是exit()方法被調(diào)用
contextlib模塊中的使用工具
@contextmanager 裝飾器能減少創(chuàng)建上下文管理器的樣板代碼量,因?yàn)椴挥镁帉懸粋€完整的類,定義__enter__ 和__exit__方法,而只需實(shí)現(xiàn)有一個yield 語句的生成器,生成想讓__enter__ 方法返回的值。
在使用@contextmanager 裝飾的生成器中,yield語句的作用是把函數(shù)的定義體分成兩部分**:yield 語句前面的所有代碼在with 塊開始時(即解釋器調(diào)用__enter__方法時)執(zhí)行,yield 語句后面的代碼在with 塊結(jié)束時(即調(diào)用__exit__ 方法時)執(zhí)行**
看一個使用contextmanager實(shí)現(xiàn)上下文管理器的例子
import
contextlib
@contextlib
.
contextmanager
def
Sample
(
)
:
def
do_something
(
)
:
print
(
'i am doing something'
)
print
(
"in __enter__"
)
yield
do_something
print
(
"in exit"
)
>>
>
with
Sample
(
)
as
sample
:
sample
(
)
in
__enter__
i am doing something
in
__exit__
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
