python的魔术方法之上下文管理

    xiaoxiao2024-12-30  70

    文章目录

    上下文管理实现类做装饰器和上下文管理增强功能

    上下文管理

    当一个对象同时实现了__enter__()和__exit__()方法,它就属于上下文管理的对象 方法意义__enter __进入与此对象相关的上下文。如果存在该方法,with语法会把该方法的返回值作为绑定到as子句中指定的变量上__exit __退出与此对象相关的上下文。 import time class Point: def __init__(self): print("1:init----------") time.sleep(1) print('init over') def __enter__(self): print('2,enter ~~~~~~~~') return 1 # as 后面的标识符拿到的就是__enter__的返回值 def __exit__(self,exc_type,exc_val,exc_tb): print('exit') f = Point() # 实例化f的时候,并不进入__enter__ with Point() as p: print('3 -----------') ---------------------------------------- 1:init---------- init over 1:init---------- init over 2,enter ~~~~~~~~ 3 ----------- exit 实例化对象的时候,并不会调用enter,进入with语句块调用__enter__方法,然后执行语句体,最后离开with语句块的时候,调用__exit__方法with 后面的对象必须有__enter__()方法和__exit__()方法,as后面的标识符拿到的是__enter__的返回值(with语法,会调用with后的对象的__enter__方法,如果有as,则将该方法的返回值赋给as子句的变量。)异常需要在with语句块中处理, 在exit方法中有return,返回值等效bool值,等效False,将会把异常向外抛出, 等效True,异常被压制,不向外抛出

    方法的参数

    __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__中处理
    最新回复(0)