この記事では主に Python での with キーワードの詳細な使用法に関する関連情報を紹介します。Python では、with キーワードはコンテキスト プロトコル オブジェクトの実装を管理するための優れたツールです。必要な方は参照してください。
" > Python 2.5 では、 with キーワードが追加されました。これにより、一般的に使用される try ... を除いて ... Finally ... パターンが再利用しやすくなります。最も古典的な例を見てください:with open('file.txt') as f: content = f.read()
db.begin() try: # do some actions except: db.rollback() raise finally: db.commit()
with transaction(db): # do some actions
with の一般的な実行プロセスは、2 つの一般的な方法で実装されます
expression の構造は次のとおりです。 with EXPR as VAR:
BLOCK
mgr = (EXPR) exit = type(mgr).exit # 这里没有执行 value = type(mgr).enter(mgr) exc = True try: try: VAR = value # 如果有 as VAR BLOCK except: exc = False if not exit(mgr, *sys.exc_info()): raise finally: if exc: exit(mgr, None, None, None)
このプロセスにはいくつかの詳細があります:
class transaction(object): def init(self, db): self.db = db def enter(self): self.db.begin() def exit(self, type, value, traceback): if type is None: db.commit() else: db.rollback()
ジェネレーターの使用
デコレーター
from contextlib import contextmanager @contextmanager def transaction(db): db.begin() try: yield db except: db.rollback() raise else: db.commit()
function
を作成します (私はクラス定義外のメソッドの代わりに関数を使用するのが好きです)。デコレーター contextmanager が呼び出され、ヘルパー メソッドを返します。このメソッドは、呼び出された後に GeneratorContextManager インスタンスを生成します。最後に、with 式の EXPR は、contentmanager デコレータによって返されるヘルパー関数を呼び出します。
with 式は、実際にヘルパー関数を呼び出すtransaction(db) を呼び出します。ヘルパー関数はジェネレーター関数を呼び出し、ジェネレーターを作成します。with 表达式调用实例对象的上下文管理器的 enter() 方法。
enter() 方法中会调用这个生成器的 next() 方法。这时候,生成器方法会执行到 yield db 处停止,并将 db 作为 next() 的返回值。如果有 as VAR ,那么它将会被赋值给 VAR 。
with 中的 BLOCK 被执行。
BLOCK 执行结束后,调用上下文管理器的 exit() 方法。 exit() 方法会再次调用生成器的 next() 方法。如果发生 StopIteration 异常,则 pass 。
如果没有发生异常生成器方法将会执行 db.commit() ,否则会执行 db.rollback() 。
再次看看上述过程的代码大致实现:
def contextmanager(func): def helper(*args, **kwargs): return GeneratorContextManager(func(*args, **kwargs)) return helper class GeneratorContextManager(object): def init(self, gen): self.gen = gen def enter(self): try: return self.gen.next() except StopIteration: raise RuntimeError("generator didn't yield") def exit(self, type, value, traceback): if type is None: try: self.gen.next() except StopIteration: pass else: raise RuntimeError("generator didn't stop") else: try: self.gen.throw(type, value, traceback) raise RuntimeError("generator didn't stop after throw()") except StopIteration: return True except: if sys.exc_info()[1] is not value: raise
总结
Python的 with 表达式包含了很多Python特性。花点时间吃透 with 是一件非常值得的事情。
一些其他的例子
锁机制
@contextmanager def locked(lock): lock.acquired() try: yield finally: lock.release()
标准输出重定向
@contextmanager def stdout_redirect(new_stdout): old_stdout = sys.stdout sys.stdout = new_stdout try: yield finally: sys.stdout = old_stdout with open("file.txt", "w") as f: with stdout_redirect(f): print "hello world"
以上がPython での with キーワードの使用の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。