有人可以在這段代碼中解釋一下generator和的想法嗎:try except
from contextlib import contextmanager
@contextmanager
def file_open(path):
try:
f_obj = open(path, 'w')
yield f_obj
except OSError:
print("We had an error!")
finally:
print('Closing file')
f_obj.close()
if __name__ == '__main__':
with file_open('test.txt') as fobj:
fobj.write('Testing context managers')
據我所知,不管try. 所以在我看來,這段代碼應該是這樣作業的:如果我們沒有例外,我們打開檔案,轉到生成器,然后我們轉到 finally 塊并從函式回傳。但我不明白generator這段代碼是如何作業的。我們只使用了一次,這就是為什么我們不能在檔案中寫入所有文本。但我認為我的想法是錯誤的。為什么?
uj5u.com熱心網友回復:
所以,一,你的實作是不正確的。即使打開失敗,您也會嘗試關閉打開的檔案物件,這是一個問題。在這種情況下,您需要做的是:
@contextmanager
def file_open(path):
try:
f_obj = open(path, 'w')
try:
yield f_obj
finally:
print('Closing file')
f_obj.close()
except OSError:
print("We had an error!")
或更簡單地說:
@contextmanager
def file_open(path):
try:
with open(path, 'w') as f_obj:
yield f_obj
print('Closing file')
except OSError:
print("We had an error!")
“發電機一般如何作業?” 我將向您推薦有關該主題的現有問題。這種特殊情況很復雜,因為使用@contextlib.contextmanager裝飾器將生成器重新用于很大程度上不相關的目的,利用它們在兩種情況下天生暫停的事實:
- 創建時(直到請求第一個值)
- 在每個
yield(請求每個后續值時)
實作背景關系管理。
contextmanager只是濫用它來制作這樣的類(實際的源代碼相當復雜,無法涵蓋邊緣情況):
class contextmanager:
def __init__(self, gen):
self.gen = gen # Receives generator in initial state
def __enter__(self):
return next(self.gen) # Advances to first yield, returning the value it yields
def __exit__(self, *args):
if args[0] is not None:
self.gen.throw(*args) # Plus some complicated handling to ensure it did the right thing
else:
try:
next(self.gen) # Check if it yielded more than once
except StopIteration:
pass # Expected to only yield once
else:
raise RuntimeError(...) # Oops, it yielded more than once, that's not supposed to happen
允許生成器的協程元素支持一種更簡單的方式來撰寫簡單的背景關系管理器。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/465647.html
標籤:Python python-3.x 发电机 上下文管理器
