• Python中with用法详解


    一 、with语句的原理

    • 上下文管理协议(Context Management Protocol):包含方法 __enter__()__exit__(),支持该协议的对象要实现这两个方法。
    • 上下文管理器(Context Manager):支持上下文管理协议的对象,这种对象实现了__enter__()__exit__()方法。上下文管理器定义执行with语句时要建立的运行时上下文,负责执行with语句块上下文中的进入与退出操作。通常使用with语句调用上下文管理器,也可以通过直接调用其方法来使用。

    说完上面两个概念,我们再从with语句的常用表达式入手,一段基本的with表达式,其结构是这样的:

    1 with EXPR as VAR:
    2 
    3     BLOCK

    其中EXPR可以是任意表达式;as VAR是可选的。其一般的执行过程是这样的:

    1. 执行EXPR,生成上下文管理器context_manager;
    2. 获取上下文管理器的__exit()__方法,并保存起来用于之后的调用;
    3. 调用上下文管理器的__enter__()方法;如果使用了as子句,则将__enter__()方法的返回值赋值给as子句中的VAR;
    4. 执行BLOCK中的表达式;
    5. 不管是否执行过程中是否发生了异常,执行上下文管理器的__exit__()方法,__exit__()方法负责执行“清理”工作,如释放资源等。如果执行过程中没有出现异常,或者语句体中执行了语句break/continue/return,则以None作为参数调用__exit__(None, None, None);如果执行过程中出现异常,则使用sys.exc_info得到的异常信息为参数调用__exit__(exc_type, exc_value, exc_traceback)
    6. 出现异常时,如果__exit__(type, value, traceback)返回False,则会重新抛出异常,让with之外的语句逻辑来处理异常,这也是通用做法;如果返回True,则忽略异常,不再对异常进行处理。

    二、自定义上下文管理器

      Pythonwith语句是提供一个有效的机制,让代码更简练,同时在异常产生时,清理工作更简单。

    # coding = utf-8
    # 2019/7/19  Luckyxxt:有趣的事,Python永远不会缺席!
    #!/usr/bin/env python
    
    class DBManager(object):
        def __init__(self):
            pass
    
        def __enter__(self):
            print('__enter__')
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('__exit__')
            return True
    
    def getInstance():
            return DBManager()
    
    with getInstance() as dbManagerIns:
        print('with demo')

      with后面必须跟一个上下文管理器,如果使用了as,则是把上下文管理器的 __enter__() 方法的返回值赋值给 target,target 可以是单个变量,或者由“()”括起来的元组(不能是仅仅由“,”分隔的变量列表,必须加“()”)

    代码运行结果如下:

    复制代码
    1 '''
    2 __enter__
    3 with demo
    4 __exit__
    5 
    6 '''
    复制代码

    结果分析:当我们使用with的时候,__enter__方法被调用,并且将返回值赋值给as后面的变量,并且在退出with的时候自动执行__exit__方法

    复制代码
     1 class With_work(object):
     2     def __enter__(self):
     3         """进入with语句的时候被调用"""
     4         print('enter called')
     5         return "xxt"
     6 
     7     def __exit__(self, exc_type, exc_val, exc_tb):
     8         """离开with的时候被with调用"""
     9         print('exit called')
    10 
    11 
    12 with With_work() as f:
    13     print(f)
    14     print('hello with')
    复制代码
    复制代码
    1 '''
    2 enter called
    3 xxt
    4 hello with
    5 exit called
    6 
    7 '''
    复制代码

    三、总结

      自定义上下文管理器来对软件系统中的资源进行管理,比如数据库连接、共享资源的访问控制等。

         

    转自:https://www.cnblogs.com/xxtalhr/p/11211347.html#_labelTop 

  • 相关阅读:
    mac上命令行解压rar
    Mac上安装PHP、Apache、MySQL
    8款不错的 CI/CD工具
    Apache 强制Http跳转Https
    使用MySQL的mysqldump命令备份数据库和把数据库备份文件恢复
    MySQL主从复制和读写分离
    Nginx参数调优
    【原创】深入理解Docker容器和镜像 -- 分析了docker的命令含义
    Elasticsearch使用备忘
    通过HTTP RESTful API 操作elasticsearch搜索数据
  • 原文地址:https://www.cnblogs.com/yunlong-study/p/12658712.html
Copyright © 2020-2023  润新知