在python中,有很多函數既可以作爲標準函數又可以作爲上下文管理器。例如open()
可以被稱爲無論是作爲:Python:標準函數和上下文管理器?
my_file=open(filename,'w')
或
with open(filename,'w') as my_file:
都讓你可以用來做任何你需要一個my_file
對象。一般來說,後者是可取的,但有時候也可能想要做前者。
我已經能夠找出如何寫一個上下文管理器,通過創建與__enter__
和__exit__
函數的類或使用上的功能的@contextlib.contextmanager
裝飾和yield
而非return
。但是,當我這樣做時,我不能再直接使用函數 - 例如,使用裝飾器,我得到一個_GeneratorContextManager
對象,而不是想要的結果。當然,如果我把它作爲一個類來做,我只會得到一個生成器類的實例,我認爲它基本上是一樣的。
那麼我怎麼能設計一個函數(或類),作爲一個函數,返回一個對象,或上下文管理器,返回_GeneratorContextManager
或類似的?
編輯:
例如,說我有如下內容(這是高度簡化的)功能:
def my_func(arg_1,arg_2):
result=arg_1+arg_2
return my_class(result)
所以函數需要一系列的參數,確實的東西與他們,和使用這些東西的結果初始化一個類,然後它返回。最終結果是我有一個my_class
的實例,就像我有一個file
對象,如果我叫open
。如果我想能夠使用此功能作爲一個上下文管理器,我可以修改它,如下所示:
@contextlib.contextmanager
def my_func(arg_1,arg_2):
result=arg_1+arg_2 # This is roughly equivalent to the __enter__ function
yield my_class(result)
<do some other stuff here> # This is roughly equivalent to the __exit__function
的上下文管理器調用時,以下哪工作得很好,但我不再得到my_class
當實例稱爲直接功能。也許我只是做錯了什麼?
編輯2:
請注意,我有完全控制權my_class
,包括增加功能的能力。根據以下公認的答案,我可以推斷出我的困難源於一個基本的誤解:我想我所說的任何東西(上面的例子中的my_func
)都需要具有__exit__
和__enter__
函數。這是不正確的。實際上,它只是功能返回(my_class
在上面的示例中)需要函數才能用作上下文管理器。
'open'是一個返回類實例的函數。無論你使用'myfile = open(filename)'還是'以open(filename)作爲myfile',它仍然是同一類的一個實例。沒有什麼改變。 – zondo
@zondo真的,我正在努力寫的功能。但是,當我將函數包裝在'@ contextlib.contextmanager'裝飾器中,並將其作爲標準函數調用時,我返回的類不是函數中的類「yield」。只有當我將其稱爲上下文管理器時,我才能獲得該類。我會添加一個簡單的例子。 – ibrewster
在你的課堂上定義一個'__call__'方法。 –