簡體   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