繁体   English   中英

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.lockNone则上述显然失败。

我的选择是:

  1. if

     def foo(self): if self.lock: with self.lock: operate(self.resource) else: operate(self.resource)
    • 缺点:过于冗长
    • pro: 不会创建不必要的threading.Lock
  2. 始终将self.lock设置为threading.Lock

    • 优点:代码简化
    • 缺点: with self.lock似乎相对昂贵(与磁盘 i/o 相比!)
  3. 定义一个简单的锁类:

     class TrivialLock(object): def __enter__(self): pass def __exit__(self, _a, _b, _c): pass def acquire(self): pass def release(self): pass

    并为R2使用它而不是None

    • 亲:简单的代码
    • 缺点:我必须定义TrivialLock

问题

  1. 社区更喜欢哪种方法?
  2. 不管(1),有没有人真正定义过类似TrivialLock东西? (我实际上希望标准库中会有类似的东西......)
  3. 我对锁定成本与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内联定义TrivalLock

self.lock = contextlib.contextmanager(lambda: (yield))()

注意括号; lambda: yield无效。 但是,生成器表达式(yield)使其成为一次性上下文管理器; 如果您尝试在第二个with语句中使用相同的值,您将收到Runtime错误,因为generator已耗尽。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM