方法的参数
__enter__方法没有其他参数。
__exit__方法有3个参数: __exit __(self, exc_type, exc_value, traceback) 这三个参数都与异常有关。如果该上下文退出时没有异常,这3个参数都为None。如果有异常,参数意义如下
exc_type,异常类型exc_value,异常的值traceback,异常的追踪信息__exit__方法返回一个等效True的值,则压制异常;否则,继续抛出异常 如下
class Point: def __init__(self, x, y): self.x = x self.y = y print(1,self) def __enter__(self): print('2 ------------') return 1 def __exit__(sefl,exc_type, exc_val, exc_tb): print(3,exc_type) print(4,exc_val) print(5,exc_tb) return 1 def __str__(self): return str((self.x,self.y)) with Point(2,3) as p: a = 1/0 # 此处除0异常,本应该抛异常,但是__exit__()方法中有return值,且等效为True,所以异常被压制,因为异常,所以'pass'并不能打印 print(6,'pass') ------------------------------------------ 1 (2, 3) 2 ------------ 3 <class 'ZeroDivisionError'> 4 division by zero 5 <traceback object at 0x00000214DE0E7408>下面的类即可以用在上下文管理,又可以用做装饰器
import time import datetime class Timed: """this is decoration""" def __init__(self, fn): self.fn = fn self.__doc__ = fn.__doc__ #实例属性更改应该在初始化配置的时候更改 self.__name__ = fn.__name__ def __enter__(self): self.start = datetime.datetime.now() return self def __exit__(self, exc_type, exc_val, exc_tb): delta = (datetime.datetime.now() - self.start).total_seconds() print("{} took {}s. context".format(self.fn.__name__, delta)) def __call__(self, *args, **kwargs): #实例功能的增加在函数调用的位置增加 start = datetime.datetime.now() ret = self.fn(*args, **kwargs) delta = (datetime.datetime.now() - start).total_seconds() print(delta) return ret @Timed # add = Timed(add) def add(x, y): '''this is add function''' time.sleep(1) v = x + y print(v) return x + y add(3, 6) print(add.__doc__,";",add.__name__) ---------------------------------------------------------------- 9 1.000373 this is add function ; add 上下文应用场景 增强功能在代码执行的前后增加代码,以增强其功能。类似装饰器的功能。资源管理打开了资源需要关闭,例如文件对象、网络连接、数据库连接等权限验证在执行代码之前,做权限的验证,在__enter__中处理