日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python一个try块后接一个或多个finally块_Python *与*语句完全等同于一个try – (除了) – finally块?...

發布時間:2024/4/19 python 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python一个try块后接一个或多个finally块_Python *与*语句完全等同于一个try – (除了) – finally块?... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我會放棄提及的范圍,因為它真的不是很相關.

with EXPR as VAR:

BLOCK

翻譯成

mgr = (EXPR)

exit = type(mgr).__exit__ # Not calling it yet

value = type(mgr).__enter__(mgr)

exc = True

try:

try:

VAR = value # Only if "as VAR" is present

BLOCK

except:

# The exceptional case is handled here

exc = False

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

raise

# The exception is swallowed if exit() returns true

finally:

# The normal and non-local-goto cases are handled here

if exc:

exit(mgr, None, None, None)

如你所見,鍵入(mgr).__ enter__被調用,如你所料,但不是在嘗試.

類型(mgr).__ exit__在退出時調用.唯一的區別是當有異常時,如果沒有退出(mgr,* sys.exc_info())路徑.這使得能夠內省和沉默錯誤,而不像finally子句可以做什么.

contextmanager并不會使這一點復雜化.只是:

def contextmanager(func):

@wraps(func)

def helper(*args, **kwds):

return _GeneratorContextManager(func, *args, **kwds)

return helper

然后看看有關的課程:

class _GeneratorContextManager(ContextDecorator):

def __init__(self, func, *args, **kwds):

self.gen = func(*args, **kwds)

def __enter__(self):

try:

return next(self.gen)

except StopIteration:

raise RuntimeError("generator didn't yield") from None

def __exit__(self, type, value, traceback):

if type is None:

try:

next(self.gen)

except StopIteration:

return

else:

raise RuntimeError("generator didn't stop")

else:

if value is None:

value = type()

try:

self.gen.throw(type, value, traceback)

raise RuntimeError("generator didn't stop after throw()")

except StopIteration as exc:

return exc is not value

except:

if sys.exc_info()[1] is not value:

raise

不重要的代碼已經消失.

首先要注意的是,如果有多個收益率,這個代碼將會出錯.

這并不明顯地影響控制流程.

考慮__enter__.

try:

return next(self.gen)

except StopIteration:

raise RuntimeError("generator didn't yield") from None

如果上下文管理器寫得很好,那永遠不會從預期的中斷.

一個區別是,如果生成器拋出StopIteration,將產生一個不同的錯誤(RuntimeError).這意味著,如果您正在運行完全任意的代碼,則該行為與正常行為不完全相同.

考慮一個非錯誤的__exit__:

if type is None:

try:

next(self.gen)

except StopIteration:

return

else:

raise RuntimeError("generator didn't stop")

唯一的區別就像以前一樣.如果你的代碼拋出StopIteration,它會影響生成器,因此contextmanager裝飾器會誤解它.

這意味著:

from contextlib import contextmanager

@contextmanager

def with_cleanup(func):

try:

yield

finally:

func()

def good_cleanup():

print("cleaning")

with with_cleanup(good_cleanup):

print("doing")

1/0

#>>> doing

#>>> cleaning

#>>> Traceback (most recent call last):

#>>> File "", line 15, in

#>>> ZeroDivisionError: division by zero

def bad_cleanup():

print("cleaning")

raise StopIteration

with with_cleanup(bad_cleanup):

print("doing")

1/0

#>>> doing

#>>> cleaning

哪個不太重要,但可以.

最后:

else:

if value is None:

value = type()

try:

self.gen.throw(type, value, traceback)

raise RuntimeError("generator didn't stop after throw()")

except StopIteration as exc:

return exc is not value

except:

if sys.exc_info()[1] is not value:

raise

這提出了與StopIteration相同的問題,但有趣的是注意到最后一部分.

if sys.exc_info()[1] is not value:

raise

這意味著如果未處理異常,則追溯將不會更改.如果它被處理但存在新的追溯,那將被提升.

這完全符合規格.

TL; DR

與實際上比實際上稍微強大一點…終于可以內省和沉默錯誤.>請注意StopIteration,否則您可以使用@contextmanager創建上下文管理器.

總結

以上是生活随笔為你收集整理的python一个try块后接一个或多个finally块_Python *与*语句完全等同于一个try – (除了) – finally块?...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。