>[success] # 定义类具有可以使用with ~~~ 1.当我们使用一些 需要执行关闭操作的 通常在代码的最后会执行.close方法,有的只需要使用with 就可以自动关闭 2.创建一个可以被with使用的类需要需要实现 __enter()__ 和 __exit__() 方法 3.执行顺序会自动先执行__enter()__ 方法后在执行 __exit__() 关闭操作 ~~~ >[danger] ##### 代码案例 ~~~ 1.编写上下文管理器的主要原理是你的代码会放到 with 语句块中执行。当出现 with 语句的时候,对象的 __enter__() 方法被 触发,它返回的值(如果有的话)会被赋值给 as 声明的变量。然后,with 语句块里面的代码开始执行。最后,__exit__() 方法被 触发进行清理工作。 2.__exit__() 方法的第三个参数包含了异常类型、异常值和追溯信息 3.iter 替代while True,第一个参数是一个回调函数 ~~~ ~~~ from socket import socket, AF_INET, SOCK_STREAM class LazyConnection: def __init__(self, address, family=AF_INET, type=SOCK_STREAM): self.address = address self.family = family self.type = type self.sock = None def __enter__(self): if self.sock is not None: raise RuntimeError('Already connected') self.sock = socket(self.family, self.type) self.sock.connect(self.address) return self.sock def __exit__(self, exc_ty, exc_val, tb): self.sock.close() # 关闭后清空对象 self.sock = None conn = LazyConnection(('www.python.org', 80)) with conn as s: # conn.__enter__() executes: connection open s.send(b'GET /index.html HTTP/1.0\r\n') s.send(b'Host: www.python.org\r\n') s.send(b'\r\n') # 替代while True resp = b''.join(iter(lambda :s.recv(2048), b'')) print(resp.decode('utf-8')) ~~~ >[danger] ##### with 嵌套with ~~~ 1.创建一个链接池 2.利用弹栈删除连接池内容并且关闭 ~~~ ~~~ from socket import socket, AF_INET, SOCK_STREAM class LazyConnection: def __init__(self, address, family=AF_INET, type=SOCK_STREAM): self.address = address self.family = family self.type = type self.connections = [] def __enter__(self): sock = socket(self.family, self.type) sock.connect(self.address) self.connections.append(sock) # 返回链接池 return sock def __exit__(self, exc_ty, exc_val, tb): # 删除关闭连接池中的对象 self.connections.pop().close() # Example use from functools import partial conn = LazyConnection(('www.python.org', 80)) with conn as s1: pass with conn as s2: pass # s1 and s2 are independent sockets ~~~