如何在代码执行期间更新传递给上下文管理器的参数?
How to update argument passed to context manager during code execution?
node
传递给上下文管理器,我想在开始时锁定它,然后做一些工作,最后解锁节点。但是,如果 node
在 with 子句内的执行过程中发生了变化,我该如何将更新后的 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
列表,但这不起作用。
编辑2:
我试过使用列表,它是这样工作的。
node = ['old-node']
with call(lockFunc, unlockFunc, node):
print 'in with'
node[0] = 'new-node'
问题是 node = 'new-node'
不会更改上下文管理器引用的对象;它改变了标识符 node
所指的内容。
你需要告诉对象改变,你只能用可变对象来做;字符串不可变。列表会起作用,但我认为 class 可能更清楚一些:
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)
我找到了更好的解决方案。
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',)
node
传递给上下文管理器,我想在开始时锁定它,然后做一些工作,最后解锁节点。但是,如果 node
在 with 子句内的执行过程中发生了变化,我该如何将更新后的 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
列表,但这不起作用。
编辑2: 我试过使用列表,它是这样工作的。
node = ['old-node']
with call(lockFunc, unlockFunc, node):
print 'in with'
node[0] = 'new-node'
问题是 node = 'new-node'
不会更改上下文管理器引用的对象;它改变了标识符 node
所指的内容。
你需要告诉对象改变,你只能用可变对象来做;字符串不可变。列表会起作用,但我认为 class 可能更清楚一些:
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)
我找到了更好的解决方案。
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',)