爲什麼不使用contextmanager?它基本上完全是你想要的。
以下是Python文檔中的規範示例。
from contextlib import contextmanager
@contextmanager
def tag(name):
print "<%s>" % name
yield
print "</%s>" % name
因此,對於你的功能,你只是做:
@contextmanager
def profile_update(inputs):
#take updates and update the database
yield "it worked"
#do maintainence processing now..
,並呼籲它,你只是做:
with profile_update(inputs) as result: #pre-yield and yield here
# do whatever while in scope
# as you move out of scope of with statement, post-yield is executed
編輯:我只是測試的東西而事實證明,使用yield語句,函數仍然執行到最後。這是一個愚蠢的例子,說明了問題的關鍵以及何時執行。
def some_generator(lst):
for elem in lst:
yield elem
lst[0] = "I WAS CHANGED POST-YIELD!!!!"
>>> q = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> gen = some_generator(q)
>>> for e in gen:
... print e, q
0 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
2 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
4 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
5 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
6 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
7 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
8 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
9 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print q
['I WAS CHANGED POST YIELD!!!', 1, 2, 3, 4, 5, 6, 7, 8, 9]
一個contextmanager有沒有需要兩個next
電話去停止迭代(和更清晰的語法)的優勢,但如果你想返回多個值什麼的,你也可以做這種方式,但你可以看到,屈服後聲明並沒有真正得到調用,直到發電機引發的next
通話的StopIteration
如果由於某種原因,你需要一個更高的程度(當它得到StopIteration
for循環結束)的控制比@contextmanager
報價,你可以等○定義一類__enter__
和__exit__
方法:
class MyContextClass(object):
# ...
def __enter__(self):
# do some preprocessing
return some_object
def __exit__(self, exc_type, exc_value, traceback):
# do some post processing
# possibly do some processing of exceptions raised within the block
if exc_type == MyCustomErrorType:
return True #don't propagate the error
我對python的線程並不熟悉,但是大多數線程模型中,啓動一個線程就像調用一個函數一樣簡單。複雜性來自於確保線程中完成的工作與線程異步發生的工作正確同步。在我看來,複雜性會與你在'#do維護處理現在......'後返回步驟中想要發生的任何程度一樣存在。如果不需要同步,那麼線程中就不需要任何同步。但是,反過來也是如此。 – 2012-07-23 16:09:36