我正在使用 python 2.7(迁移尚未完成)并尝试构建一个聚合类(Cluster),它提供与其单个项目(节点)相同的上下文管理器功能(保留)。理想情况下,我希望在不重构包含对象节点的上下文管理器功能的情况下做到这一点。如果它有单独的 enter() 和 exit() 方法,也许我会直接在 Cluster.reserved() 上下文管理器函数中调用它们。但我认为可能有更优雅的方式来做到这一点。我用 ExitStack 尝试了以下代码:
from contextlib import contextmanager
from contextlib2 import ExitStack
class Node:
def __init__(self, id):
self._id = id
@contextmanager
def reserved(self):
print("Node {} reserved".format(self._id))
try:
yield
except:
print("Exception while handling node")
finally:
print("Node released")
def reserve(self):
print("Node {} reserved".format(self._id))
def release(self):
print("Node {} released".format(self._id))
class Cluster:
def __init__(self, id):
self._id = id
self._nodes = [Node(1), Node(2), Node(3), Node(4)]
@contextmanager
def reserved(self):
with ExitStack() as cm:
cm.enter_context(node.reserved() for node in self._nodes)
print("Cluster {} reserved".format(self._id))
try:
yield
except:
print("Exception while handling cluster")
finally:
print("Cluster released")
@contextmanager
def reserved2(self):
with ExitStack() as cm:
for node in self._nodes:
reserve = node.reserve()
cm.callback(node.release(), reserve)
print("Cluster {} reserved".format(self._id))
try:
yield
except:
print("Exception while handling cluster")
finally:
print("Cluster released")
node = Node(10)
with node.reserved():
print('Node {} handled'.format(node._id))
cluster = Cluster(10)
with cluster.reserved2():
print('Cluster {} handled'.format(cluster._id))
第一个函数 reserved() 返回
AttributeError: type object 'generator' has no attribute '__exit__'
而第二个在保留所有节点后并没有真正产生。想知道处理这个问题的正确方法是什么......