【发布时间】:2015-06-06 19:08:18
【问题描述】:
我正在尝试创建一个 @synchronized 包装器,该包装器为每个对象创建一个 Lock 并使方法调用线程安全。如果我可以访问包装方法中的方法的method.im_self,我只能这样做。
class B:
def f(self): pass
assert inspect.ismethod( B.f ) # OK
assert inspect.ismethod( B().f ) # OK
print B.f # <unbound method B.f>
print B().f # <bound method B.f of <__main__.B instance at 0x7fa2055e67e8>>
def synchronized(func):
# func is not bound or unbound!
print func # <function f at 0x7fa20561b9b0> !!!!
assert inspect.ismethod(func) # FAIL
# ... allocate one lock per C instance
return func
class C:
@synchronized
def f(self): pass
(1) 令人困惑的是,传递给我的装饰器的 func 参数在传递给包装器生成器之前会更改类型。这似乎是粗鲁和不必要的。为什么会这样?
(2) 是否有一些装饰器魔术,我可以通过它对对象互斥锁进行方法调用(即每个对象一个锁,而不是每个类)。
更新:@synchronized(lock) 包装器有很多示例。然而,我真正想要的是@synchronized(self)。我可以这样解决:
def synchronizedMethod(func):
def _synchronized(*args, **kw):
self = args[0]
lock = oneLockPerObject(self)
with lock: return func(*args, **kw)
return _synchronized
但是,因为它更有效,我更喜欢:
def synchronizedMethod(func):
lock = oneLockPerObject(func.im_self)
def _synchronized(*args, **kw):
with lock: return func(*args, **kw)
return _synchronized
这可能吗?
【问题讨论】:
标签: python decorator python-decorators