zoukankan      html  css  js  c++  java
  • Python Day 51 浅淡python中with的用法,上下文管理器

      #案例一

    class Foo(object):
    
        def __init__(self):
            print('实例化一个对象')
    
        def __enter__(self):
            print('进入')
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('退出')
    
    obj = Foo()
    
    with obj:
        print('正在执行')
    
    
    #上面代码执行结果为:
    实例化一个对象
    进入
    正在执行
    退出
    
    #结论
    我们知道,实例化Foo,得到obj对象,会执行Foo的__init__方法,也就是打印了第一句;
    按照,程序从上至下执行,应该会打印“正在执行”才对,为什么会在它之前先打印了进入,在它之后打印了退出呢?
     
    因为我们在定义Foo时,定义了__enter__和__exit__方法,那么我们实例化的对象obj就是一个上下文管理器,
    即含有__enter__和__exit__方法的对象就是上下文管理器。
    
    with 上下文管理器:
         语句体
    
    当with遇到上下文管理器,就会在执行语句体之前,先执行上下文管理器的__enter__方法,然后再执行语句体,执行完语句体后,最后执行__exit__方法
     
    这也就是为什么会出现文章开头的情况的原因。

      ##案例二

    class Foo(object):
    
        def __init__(self):
            print('实例化一个对象')
    
        def __enter__(self):
            print('进入')
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('退出')
         # return True
    
    obj = Foo()
    
    with obj:
        raise ImportError
        print('正在执行')

      #结果如下

      #把上面代码中我们注释掉的那一行代码取消注释,结果如下

      我们会发现,虽然我们故意在语句体中抛出一个错误,按照正常情况,执行到报错地方就不会执行了,而__exit__是在语句体执行完之后执行的,但还是执行了__exit__方法;当我们在__exit__中给一个返回值为Ture时,就会忽略错误。

      #结论

    #结论
    所有我们可以发现
    with语句类似
      try :
      except:
      finally:
    的功能:但是with语句更简洁。而且更安全。代码量更少。
       出现异常时,如果 __exit__ 返回 False(默认不写返回值时,即为False),则会重新抛出异常,让with 之外的语句逻辑来处理异常,这也是通用做法;如果返回 True,则忽略异常,不再对异常进行处理

      ##案例三

    class Foo(object):
    
        def __init__(self):
            print('实例化一个对象')
    
        def __enter__(self):
            print('进入')
            # return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('退出')
    
    
    with Foo() as obj:
        print(obj,type(obj))
        print('正在执行')

      #结果

      #把上面代码中我们注释掉的那一行代码取消注释,结果如下

      #结论

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

      ##案例四

    我们经常会看到这样的代码:
    with open("/tmp/foo.txt") as file:
        data = file.read()

      #结论

    这里使用了 with 语句,不管在处理文件过程中是否发生异常,都能保证 with 语句执行完毕后已经关闭了打开的文件句柄。如果使用传统的 try/finally 范式,则要使用类似如下代码:
    somefile = open(r'somefileName')
    try:
        for line in somefile:
            print line
            # ...more code
    finally:
        somefile.close()
    
    比较起来,使用 with 语句可以减少编码量。已经加入对上下文管理协议支持的还有模块 threading、decimal 等。

      #补充

    with只能配合上下文管理器使用,常见的上下文管理器有:
    file
    decimal.Context
    thread.LockType
    threading.Lock
    threading.RLock
    threading.Condition
    threading.Semaphore
    threading.BoundedSemaphore
  • 相关阅读:
    jQuery 基本选择器
    JavaScriptif while for switch流程控制 JS函数 内置对象
    JavaScrip基本语法
    数据库 存储引擎 表的操作 数值类型 时间类型 字符串类型 枚举集合 约束
    数据库基础知识 管理员 用户登录授权的操作
    粘包的产生原理 以及如何解决粘包问题
    socket TCP DPT 网络编程
    2018年年终总结
    Android技术分享
    No accelerator found
  • 原文地址:https://www.cnblogs.com/liangzhenghong/p/11134572.html
Copyright © 2011-2022 走看看