一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語(yǔ)言編程技術(shù)及教程分享平臺(tái)!
分類(lèi)導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Python - Python中的With語(yǔ)句的使用及原理

Python中的With語(yǔ)句的使用及原理

2020-07-29 23:53Yujiaao Python

這篇文章主要介紹了Python中的With語(yǔ)句的使用及原理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

總覽

在Python中,您需要通過(guò)打開(kāi)文件來(lái)訪問(wèn)文件。您可以使用 open()函數(shù)來(lái)實(shí)現(xiàn)。Open 返回一個(gè)文件對(duì)象,該文件對(duì)象具有用于獲取有關(guān)已打開(kāi)文件的信息和對(duì)其進(jìn)行操作的方法和屬性。

with 語(yǔ)句

使用 “with” 語(yǔ)句,使代碼簡(jiǎn)潔,處理異常也更優(yōu)雅。

“with語(yǔ)句通過(guò)封裝常用的準(zhǔn)備工作和清除任務(wù)來(lái)簡(jiǎn)化異常處理。”

此外,它將自動(dòng)關(guān)閉文件。with 語(yǔ)句提供了一種確保始終使用清理的方法。

如果沒(méi)有 with 語(yǔ)句,我們將編寫(xiě)如下內(nèi)容:

?
1
2
3
4
file = open("welcome.txt")
data = file.read()
print(data)
file.close() # 文件用完一定要關(guān)閉

with 語(yǔ)句用法

'with' 語(yǔ)句是一個(gè)新的控制流結(jié)構(gòu),其基本結(jié)構(gòu)為:

?
1
2
with expression [as variable]:
  with-block

使用 with 打開(kāi)文件非常簡(jiǎn)單:使用open(filename) as file:

?
1
2
3
4
5
with open("welcome.txt") as file: # file 做為對(duì)文件對(duì)象的引用
 
  data = file.read()
 
  # 使用 data 做點(diǎn)啥

在寫(xiě)入模式下打開(kāi)output.txt

?
1
2
3
with open('output.txt', 'w') as file: # 輸出到file
 
  file.write('Hi there!')

注意,我們不必編寫(xiě) file.close()。會(huì)被自動(dòng)調(diào)用。

原理

' with '語(yǔ)句簡(jiǎn)化了以前使用try...finally塊來(lái)確保執(zhí)行清除代碼的代碼。在本節(jié)中,我將討論通常使用的語(yǔ)句。在下一節(jié)中,我將檢查實(shí)現(xiàn)細(xì)節(jié),并說(shuō)明如何編寫(xiě)用于此語(yǔ)句的對(duì)象。

with 后面的表達(dá)式需支持上下文管理協(xié)議 (即,__enter__() 和__exit__() 方法)。

?
1
2
with expression [as variable]:
  with-block

在執(zhí)行 with-block 之前調(diào)用對(duì)象的__enter __() 方法,因此可以運(yùn)行setup設(shè)置代碼??梢阅苓^(guò) as 把表達(dá)式結(jié)果綁定到變量 variable(注意這里不是賦值到變量 variable)。

with 塊的執(zhí)行完成后,即使該塊引發(fā)了異常,該對(duì)象的 __exit__() 方法也會(huì)被調(diào)用,因此可以運(yùn)行清理代碼。

要在Python 2.5中啟用該語(yǔ)句,您需要在模塊中添加以下指令:

?
1
from __future__ import with_statement

該語(yǔ)句將始終在 Python 2.6 中啟用。

現(xiàn)在,一些標(biāo)準(zhǔn)的 Python 對(duì)象支持上下文管理協(xié)議,并且可以與 'with' 語(yǔ)句一起使用。文件對(duì)象即是其中之一:

?
1
2
3
4
with open('/etc/passwd', 'r') as f:
  for line in f:
    print line
    ... 更多 ...

執(zhí)行此語(yǔ)句后,即使for循環(huán)在代碼塊中途出現(xiàn)異常,f中的文件對(duì)象也將自動(dòng)關(guān)閉。

注意: 在這種情況下,f 是 open() 創(chuàng)建的同一對(duì)象 ,因?yàn)?file.__enter__()返回 self。

threading 模塊的鎖和條件變量也支持 'with' 語(yǔ)句:

?
1
2
3
4
lock = threading.Lock()
with lock:
  # 代碼臨界區(qū)
  ...

該鎖在執(zhí)行 with 塊之前獲取,并在該塊完成后始終釋放。

decimal模塊中 的新 localcontext() 函數(shù)使保存和還原當(dāng)前decimal上下文變得容易,它封裝了計(jì)算所需的精度和舍入特征:

?
1
2
3
4
5
6
7
8
9
10
from decimal import Decimal, Context, localcontext
 
# 顯示默認(rèn)精度: 28 位數(shù)字
v = Decimal('578')
print v.sqrt()
 
with localcontext(Context(prec=16)):
  # 本代碼塊中使用16位精度.
  # 原始上下文將在退出塊后恢復(fù).
  print(v.sqrt())

編寫(xiě)上下文管理器

在幕后,with 語(yǔ)句相當(dāng)復(fù)雜。大多數(shù)人只會(huì)在與現(xiàn)有對(duì)象一起使用 'with',并且不需要知道這些詳細(xì)信息,如果您想讓自己寫(xiě)的類(lèi)也支持 with語(yǔ)句,那就需要了解上下文管理器了。

上下文管理協(xié)議的高級(jí)解釋是:

  • 該表達(dá)式將被求值并應(yīng)產(chǎn)生一個(gè)稱(chēng)為``context manager''的對(duì)象。上下文管理器必須包含 __enter__() 和 __exit__() 方法。
  • 上下文管理器的 __enter__() 方法被調(diào)用。返回的值分配給 var 。如果不存在as var子句,則僅丟棄該值。
  • with 塊中的代碼被執(zhí)行。
  • 如果 with 塊引發(fā)異常, 則使用異常詳細(xì)信息調(diào)用__exit__(type,value,traceback),該異常詳細(xì)信息由sys.exc_info() 返回 。該方法的返回值控制是否重新引發(fā)異常:任何 False 值都會(huì)重新引發(fā)異常,True會(huì)抑制異常。通常很少需要抑制異常,因?yàn)槿绻@樣做,包含 'with' 語(yǔ)句的代碼的作者將永遠(yuǎn)不會(huì)意識(shí)到任何錯(cuò)誤。
  • 如果 with 塊沒(méi)有引發(fā)異常,則仍然會(huì)調(diào)用__exit__()方法,此時(shí)參數(shù)type,value和traceback都是 None。

讓我們考慮一個(gè)例子。我不會(huì)提供詳細(xì)的代碼,而只會(huì)概述支持事務(wù)的數(shù)據(jù)庫(kù)所必需的方法。

(對(duì)于不熟悉數(shù)據(jù)庫(kù)術(shù)語(yǔ)的人:將對(duì)數(shù)據(jù)庫(kù)的一組更改分組為一個(gè)事務(wù)。可以提交事務(wù),這意味著將所有更改都寫(xiě)入數(shù)據(jù)庫(kù),也可以回滾,這意味著將所有更改都丟棄并刪除。數(shù)據(jù)庫(kù)未更改。有關(guān)更多信息,請(qǐng)參見(jiàn)任何數(shù)據(jù)庫(kù)教科書(shū)。)

假設(shè)有一個(gè)代表數(shù)據(jù)庫(kù)連接的對(duì)象。我們的目標(biāo)是讓用戶編寫(xiě)如下代碼:

?
1
2
3
4
5
db_connection = DatabaseConnection()
with db_connection as cursor:
  cursor.execute('insert into ...')
  cursor.execute('delete from ...')
  # ... more operations ...

如果塊中的代碼完美運(yùn)行,則應(yīng)該提交事務(wù);如果有異常,則應(yīng)回滾事務(wù)。這是我假設(shè)的DatabaseConnection的基本接口:

?
1
2
3
4
5
6
class DatabaseConnection:
  ...
  def __enter__ (self):
    # Code to start a new transaction
    cursor = self.cursor()
    return cursor

該__enter __()方法是很簡(jiǎn)單的,只有到啟動(dòng)新的事務(wù)。對(duì)于此應(yīng)用程序,結(jié)果光標(biāo)對(duì)象將是有用的結(jié)果,因此該方法將返回它。然后,用戶可以添加as cursor到其 with 語(yǔ)句中,以將游標(biāo)綁定到變量名。

?
1
2
3
4
5
6
7
8
class DatabaseConnection:
  # Database interface
  def cursor (self):
    "Returns a cursor object and starts a new transaction"
  def commit (self):
    "Commits current transaction"
  def rollback (self):
    "Rolls back current transaction"

該__exit __()方法有點(diǎn)復(fù)雜,該方法必須檢查是否發(fā)生異常。如果沒(méi)有異常,則提交事務(wù)。如果存在異常,則事務(wù)將回滾。

在下面的代碼中,執(zhí)行會(huì)從函數(shù)的末尾開(kāi)始,并返回默認(rèn)值None。 None為假,因此將自動(dòng)重新引發(fā)異常。如果需要,可以更加明確,并 在標(biāo)記的位置添加return語(yǔ)句。

?
1
2
3
4
5
6
7
8
9
10
class DatabaseConnection:
  ...
  def __exit__ (self, type, value, tb):
    if tb is None:
      # No exception, so commit
      self.commit()
    else:
      # Exception occurred, so rollback.
      self.rollback()
      # return False

contextlib 模塊

contextlib 模塊提供了一些功能和裝飾器,這些功能和裝飾器對(duì)于編寫(xiě)與 'with' 語(yǔ)句一起使用的對(duì)象很有用。

裝飾器稱(chēng)為 contextmanager,它使您可以編寫(xiě)一個(gè)生成器函數(shù),而不用定義一個(gè)新類(lèi)。生成器應(yīng)恰好產(chǎn)生一個(gè)值。直到y(tǒng)ield的代碼 將作為_(kāi)_enter __()方法執(zhí)行,并且yield的值將是該方法的返回值,該返回值將綁定到' with '語(yǔ)句的as子句中的變量(如果有)。屈服后的代碼將在 __exit __()方法中執(zhí)行。塊中引發(fā)的任何異常都將由yield語(yǔ)句引發(fā)。

上一節(jié)中的數(shù)據(jù)庫(kù)示例可以使用以下裝飾器編寫(xiě)為:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from contextlib import contextmanager
 
@contextmanager
def db_transaction (connection):
  cursor = connection.cursor()
  try:
    yield cursor
  except:
    connection.rollback()
    raise
  else:
    connection.commit()
 
db = DatabaseConnection()
with db_transaction(db) as cursor:

該contextlib模塊還具有嵌套(MGR1, MGR2,...)功能結(jié)合了一些上下文管理器,所以你不需要寫(xiě)嵌套“不與 ”語(yǔ)句。在此示例中,單個(gè)' with '語(yǔ)句既啟動(dòng)數(shù)據(jù)庫(kù)事務(wù)并獲取線程鎖:

?
1
2
lock = threading.Lock()
with nested (db_transaction(db), lock) as (cursor, locked):

最后,Closeing(object)函數(shù)返回object,以便可以將其綁定到變量,并object.close()在塊的末尾調(diào)用。

?
1
2
3
4
5
6
import urllib, sys
from contextlib import closing
 
with closing(urllib.urlopen('http://bixuebihui.com')) as f:
  for line in f:
    sys.stdout.write(line)

參考:

https://docs.python.org/2.5/whatsnew/pep-343.html

到此這篇關(guān)于Python中的With語(yǔ)句的使用及原理的文章就介紹到這了,更多相關(guān)Python With語(yǔ)句內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://segmentfault.com/a/1190000023415387

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲国产精品第一页 | 欧美激情精品久久久久久不卡 | 青草视频在线观看免费视频 | freesex性欧美炮机喷潮 | 免费福利资源站在线视频 | 日本在线观看www鲁啊鲁视频 | 成人欧美一区二区三区 | 99久久香蕉国产线看观香 | 国产欧美日韩不卡一区二区三区 | 99精品久久精品一区二区 | 98色花堂永久地址国产精品 | 精品图区 | 精品综合一区二区三区 | 国产成人在线视频播放 | 我的年轻漂亮继坶三级 | 日韩精品特黄毛片免费看 | 韩国三级hd中文字幕李采潭 | 日本三级s级在线播放 | 91porn在线观看国产 | 精品久久久久中文字幕日本 | 大乳一级一区二区三区 | 日本丰满大乳乳奶 | 翁熄性放纵交换300章 | 亚洲四虎永久在线播放 | 男人曰女人 | 嘉嘉的丝袜美腿白丝 | 日本精品一卡二卡≡卡四卡 | 91插视频| 日本特黄一级大片 | 国产香蕉97碰碰久久人人 | 555www成人网 | 国产1区2区三区不卡 | 99热久久这里只有精品6国产网 | 高清男的插曲女的 欢迎你老狼 | 亚洲国产情侣偷自在线二页 | 精品手机在线1卡二卡3卡四卡 | 男女男精品视频免费观看 | 99视频在线免费观看 | 亚洲欧美国产另类视频 | 精品亚洲视频在线 | 日本免费三片在线观看 |