假设我们有一个类“A”,它本身就充当上下文管理器,所以它实现了
def __enter__()
def __exit__()
界面。客户端代码直接使用with
语句生成“A”对象是有效的。
现在,我们还有另一个类“B”,它封装了其他功能,也使用了“A”对象。
如果我们也想让“B”充当上下文管理器,那么管理它的“A”实例的正确方法是什么?
是否应该在“B”上调用__enter__
和(分别)调用它的 A 对象实例?或者,还有更好的方法?__exit__
__enter__
__exit__
举一个具体的例子(这不是我在我的应用程序中使用的,这只是我想到的第一个非抽象例子)考虑两个类
DatabaseConnection
DatabaseConnectionPool
单独使用一个是有效DatabaseConnection
的,因此DatabaseConnection
实现了上下文管理器接口。
DatabaseConnectionPool
使用了几个DatabaseConnections
以及其他一些零碎的东西。使用DatabaseConnectionPool
(即“with”)应该对它的实例进行设置和拆除DatabaseConnection
(以及它可能想做的任何其他事情)
更新: 我编写了一些测试代码,希望能提供以下输出:
在 Outer 上调用 Enter 在 Inner 上调用 Enter 在外部环境中... do_foo 调用! 还在用外... 在内部调用退出 在外部调用的退出 使用外部完成
但我得到以下信息:
在 Outer 上调用 Enter 在 Inner 上调用 Enter 在内部调用退出 在外部环境中... do_foo 调用! 还在用外... 在外部调用的退出 使用外部完成
代码:
class Inner(object):
def __enter__(self):
print "Enter invoked on Inner"
return self
def __exit__(self, typ, val, tb):
print "Exit invoked on inner"
def do_foo(self):
print "do_foo invoked!"
class Outer(object):
def __init__(self):
self._inner = Inner()
def __enter__(self):
print "Enter invoked on Outer"
with self._inner as ctx:
return self
def __exit__(self, typ, val, tb):
print "Exit invoked on outer"
with Outer() as outer:
print "Within outer context..."
outer._inner.do_foo()
print "Still using outer..."
print "Done using outer"
关于如何使这项工作的任何想法?