Python小推车python学习

Python学习打call第三十一天:上下文管理器

2019-03-03  本文已影响28人  暖A暖

1.什么是上下文管理

2.如何实现上下文管理器

class Student:
    def __init__(self):   # 第一步:进入上下文之前会调用初始化方法
        print('init')
        self.name = '张三'
        self.age = 27

    def __enter__(self):   # 第二步:进入上下文会调用这个方法,return返回的结果会通过as关键字赋值给后面的变量
        print('enter')
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('exit')      # 第四步:执行完毕语句块后,会调用__exit__方法退出上下文

with Student() as stu:
    print(stu)              # 第三步:调用了__enter__后,会执行上下文的语句块

3.with 语句的上下文管理

# 示例1
class Student:
    def __init__(self):
        print('init')
        self.name = '张三'
        self.age = 27

    def __enter__(self):   
        print('enter')
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('exit')      

# 即使在上下文语句中出现异常,那么退出上下文的时候,也会执行__exit__方法
with Student() as stu:
    raise Exception('自定义抛出一个异常')  


# 示例2(数据库连接)
class Data:
    def __init__(self):
        self.influxdb_client_1 = InfluxDBClient(host='1.1.1.1', port=8086, database='database1', )
        self.influxdb_client_2 = InfluxDBClient(host='2.2.2.2', port=8086, database='database1', )
  
    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.influxdb_client_1.close()
        self.influxdb_client_2.close()
    
    def get_metrics(self, server_name):
        print('从influxdb中查询到所有的metrics')
        return '将所有的metrics返回'

# 使用上下文管理查询数据的过程, 即使中间抛出异常,也会执行__exit__方法,关闭数据库连接
with Data() as data:
    data.get_metrics(server1)

4.contextlib模块

# 让普通函数也可以使用上下文管理, 前提条件是add函数必须是生成器函数,且只有yield语句
from contextlib import contextmanager
@contextmanager
def add(x, y):
    print('__enter__')   # 第二部:调用__enter__
    yield x + y          # 第二部:返回__enter__函数的返回值给obj对象
    print('__exit__')    # 第四部:调用__exit__

with add(1,2) as obj:
    print(obj)            # 第三部:执行上下文语句块

5.functools.total_ordering装饰器

# 让实例比较大小很方便
from functools import total_ordering
@total_ordering
class XKD:
    def __init__(self, price):
        self.__price = price
    @property
    def price(self):
        return self.__price
    # 如果需要比较大小,必须实现'< > <= >='一个其中的一个
    def __lt__(self, other):
        return self.__price < other.__price
xkd1 = XKD(100)
xkd2 = XKD(200)
print(xkd1 <= xkd2)

参考:https://www.9xkd.com/user/plan-view.html?id=2808881948

上一篇下一篇

猜你喜欢

热点阅读