在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__'方法。 –