Python中的琐碎上下文管理器

2024-10-02 02:25:58 发布

您现在位置: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是{},则上述操作显然失败。在

我的选择是:

  1. if

    ^{pr2}$
    • 缺点:太冗长了
    • 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
    

    并用它代替None表示R2。在

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

问题

  1. 社区更喜欢哪种方法?在
  2. 不管(1),有人真的定义 TrivialLock?(我其实以为这样的事情会 在标准库中…)
  3. 我的观察结果是锁定成本与 write符合预期?在

Tags: selflock类型定义objectdefpassresource
1条回答
网友
1楼 · 发布于 2024-10-02 02:25:58

我会定义TrivialLock。不过,这可能更为简单,因为您只需要一个上下文管理器,而不是一个锁。在

class TrivialLock(object):
    def __enter__(self):
        pass
    def __exit__(*args):
        pass

您可以使用contextlib使其更加简单:

^{pr2}$

而且由于yield可以是一个表达式,所以可以用内联定义TrivalLock

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

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

相关问题 更多 >

    热门问题