node
被传递给上下文管理器,我想在开始时锁定,然后做一些工作,最后解锁节点。但是如果在with子句中执行期间更改了node
,我该如何将更新后的node
传递给unlockFunc
?
此代码在python 2.7中运行
from contextlib import contextmanager
@contextmanager
def call(begin, end, *args, **kwargs):
begin(*args, **kwargs)
try:
yield
finally:
end(*args, **kwargs)
def lockFunc(*args):
print 'in lockFunc'
print 'lock %s' %args[0]
def unlockFunc(*args):
print 'in unlockFunc'
print 'unlock %s' %args[0]
node = 'old-node'
with call(lockFunc, unlockFunc, node):
print 'in with'
# update node value here
node = 'new-node'
但输出是
in lockFunc
lock old-node
in with
in unlockFunc
unlock old-node
如何让unlockFunc
知道node
已被更改。
编辑:我已尝试将node
列入清单,但这不起作用。
EDIT2: 我尝试使用列表,它以这种方式工作。
node = ['old-node']
with call(lockFunc, unlockFunc, node):
print 'in with'
node[0] = 'new-node'
答案 0 :(得分:1)
问题是node = 'new-node'
没有改变contextmanager引用的对象;它会更改标识符node
所指的内容。
你需要告诉对象改变,你只能用一个可变对象来做;字符串不可变。列表可以工作,但我认为一个类可能更清楚一点:
from contextlib import contextmanager
class Node(object):
def __init__(self,value):
self.value=value
def update(self, newvalue):
self.value = newvalue
def __str__(self):
return str(self.value)
@contextmanager
def call(begin, end, *args, **kwargs):
begin(*args, **kwargs)
try:
yield
finally:
end(*args, **kwargs)
def lockFunc(*args):
print 'in lockFunc'
print 'lock %s' %args[0]
def unlockFunc(*args):
print 'in unlockFunc'
print 'unlock %s' %args[0]
node = Node('old-node')
with call(lockFunc, unlockFunc, node):
print 'in with'
# update node value here
node.update('new-node')
产生
in lockFunc
lock old-node
in with
in unlockFunc
unlock new-node
(Ubuntu 14.04,Python 2.7.6)
答案 1 :(得分:0)
我找到了更好的解决方案。
class call(object):
def __init__(self,begin, end, *args, **kwargs):
self.begin = begin
self.end = end
self.args = args
self.kwargs = kwargs
def __enter__(self):
self.begin(*self.args, **self.kwargs)
return self
def __exit__(self,exc_type,exc_val,trcback):
self.end(*self.args, **self.kwargs)
def lockFunc(*args):
print 'in lockFunc', args
print 'lock %s' %args
def unlockFunc(*args):
print 'in unlockFunc'
print 'unlock %s' %args
node = 'old-node'
with call(lockFunc, unlockFunc, node) as c:
print 'in with'
# update node value here
c.args = ('new-node',)