Python 还提供了⼀个 contextmanager 的装饰器,更进⼀步简化了上下⽂管理器的实现⽅式。通过
yield 将函数分割成两部分,yield 之前的语句在 __enter__ ⽅法中执⾏,yield 之后的语句在 __exit__⽅法中执⾏。紧跟在 yield 后⾯的值是函数的返回值。
from contextlib import contextmanager
@contextmanager
def func(path, mode):
f = open(path, mode)
yield f
f.close()
1、简单猜想contextmanager源码:
class manager: def __init__(self, path, mode): self.func = func(path, mode) self.path = path self.mode = mode def __enter__(self): return next(self.func) def __exit__(self, *args): try: next(self.func) except StopIteration: print("catch stopIter!") def func(file, mode): print("opening") f = open(file, mode) yield f print("closing") f.close() if __name__ == '__main__': with manager("./out.txt", "w") as f: f.write("2013.5.13")
2、进阶猜想contextmanager源码:
class manager: def __init__(self, func): self.func = func self.args = None self.kwargs = None self.generator = None def __enter__(self): self.generator = self.func(*self.args, **self.kwargs) return next(self.generator) def __exit__(self, *args): try: next(self.generator) except StopIteration: print("catch stopIter!") def __call__(self, *args, **kwargs): self.args = args self.kwargs = kwargs return self @manager def func(file, mode): print("opening") f = open(file, mode) yield f print("closing") f.close() if __name__ == '__main__': with func("./out.txt", "w") as f: f.write("2023.5.13")
在下新手,代码逻辑有点乱,还有优化空间。大概能实现contextmanager装饰器类似功能。