Python 中的简单上下文管理器
Trivial context manager in Python
我的资源可以是需要锁定的 R1
类型或 R2
类型
不需要它:
class MyClass(object): # broken
def __init__ (self, ...):
if ...:
self.resource = R1(...)
self.lock = threading.Lock()
else:
self.resource = R2(...)
self.lock = None
def foo(self): # there are many locking methods
with self.lock:
operate(self.resource)
如果 self.lock
是 None
,上述显然失败了。
我的选择是:
if
:
def foo(self):
if self.lock:
with self.lock:
operate(self.resource)
else:
operate(self.resource)
- 缺点:太冗长
- pro: 不会创建不必要的
threading.Lock
始终将 self.lock
设置为 threading.Lock
- 亲:代码被简化了
- 缺点:
with self.lock
看起来比较贵
(媲美盘i/o!)
定义一个简单的锁class:
class TrivialLock(object):
def __enter__(self): pass
def __exit__(self, _a, _b, _c): pass
def acquire(self): pass
def release(self): pass
并使用它代替 None
用于 R2
。
- 专业版:简单代码
- 缺点:我必须定义
TrivialLock
问题
- 社区更喜欢哪种方法?
- 不管 (1),有没有人真正定义类似
TrivialLock
? (我实际上期望类似的东西会是
在标准库中...)
- 我观察到锁定成本与
write
符合预期?
我会定义TrivialLock
。不过,它可能更简单,因为您只需要一个上下文管理器,而不是锁。
class TrivialLock(object):
def __enter__(self):
pass
def __exit__(*args):
pass
您可以使用 contextlib
:
使这更简单
import contextlib
@contextlib.contextmanager
def TrivialLock():
yield
self.lock = TrivialLock()
并且因为 yield
可以是一个表达式,所以你可以定义 TrivalLock
inline 代替:
self.lock = contextlib.contextmanager(lambda: (yield))()
注意括号; lambda: yield
无效。但是,生成器表达式 (yield)
使它成为 single-use 上下文管理器;如果您尝试在第二个 with
语句中使用相同的值,则会收到 Runtime
错误,因为 generator
已用尽。
我的资源可以是需要锁定的 R1
类型或 R2
类型
不需要它:
class MyClass(object): # broken
def __init__ (self, ...):
if ...:
self.resource = R1(...)
self.lock = threading.Lock()
else:
self.resource = R2(...)
self.lock = None
def foo(self): # there are many locking methods
with self.lock:
operate(self.resource)
如果 self.lock
是 None
,上述显然失败了。
我的选择是:
if
:def foo(self): if self.lock: with self.lock: operate(self.resource) else: operate(self.resource)
- 缺点:太冗长
- pro: 不会创建不必要的
threading.Lock
始终将
self.lock
设置为threading.Lock
- 亲:代码被简化了
- 缺点:
with self.lock
看起来比较贵 (媲美盘i/o!)
定义一个简单的锁class:
class TrivialLock(object): def __enter__(self): pass def __exit__(self, _a, _b, _c): pass def acquire(self): pass def release(self): pass
并使用它代替
None
用于R2
。- 专业版:简单代码
- 缺点:我必须定义
TrivialLock
问题
- 社区更喜欢哪种方法?
- 不管 (1),有没有人真正定义类似
TrivialLock
? (我实际上期望类似的东西会是 在标准库中...) - 我观察到锁定成本与
write
符合预期?
我会定义TrivialLock
。不过,它可能更简单,因为您只需要一个上下文管理器,而不是锁。
class TrivialLock(object):
def __enter__(self):
pass
def __exit__(*args):
pass
您可以使用 contextlib
:
import contextlib
@contextlib.contextmanager
def TrivialLock():
yield
self.lock = TrivialLock()
并且因为 yield
可以是一个表达式,所以你可以定义 TrivalLock
inline 代替:
self.lock = contextlib.contextmanager(lambda: (yield))()
注意括号; lambda: yield
无效。但是,生成器表达式 (yield)
使它成为 single-use 上下文管理器;如果您尝试在第二个 with
语句中使用相同的值,则会收到 Runtime
错误,因为 generator
已用尽。