zoukankan      html  css  js  c++  java
  • with as 如何工作

    with as 如何工作

     

    with如何工作?

    Python对with的处理还是很机智滴.基本思想就是with所求值的对象必须有一个__enter__()方法,一个__exit__()方法

    紧跟with后面的语句被求值后,返回对象的__enter__()方法被调用,这个方法的返回值将被赋值给as后面的变量,当with后面的代码块全部被执行完之后,将调用前面返回对象的__exit__()方法.

    下面例子可以具体说明with如何工作

    复制代码
    class Sample:
        def __enter__(self):
            print("in __enter__")
            return "foo"  # 返回值赋值给了"sample",所以下面代码打印的foo
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("in __exit__()")
    
    
    def get_sample():
        return Sample()
    
    with get_sample() as sample:
        print("sample", sample)
    复制代码

    运行代码,输出如下

    in __enter__
    sample foo
    in __exit__()

    1,__enter__()方法被执行

    2,__enter__()方法返回的值 - 这个例子中的"foo",赋值给变量"sample"

    3,执行代码块,打印变量"smple"的值为"foo"

    4,__exit__()方法被调用

    with真正强大之处是他可以处理异常,可能你已经注意到Sample类的__exit__方法有三个参数

    exc_type,exc_val,exc_tb.这些参数在异常处理中相当有用,我们开修改下代码:

    复制代码
    class Sample:
        def __enter__(self):
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("type: ", exc_type)
            print("value: ", exc_val)
            print("trace: ", exc_tb)
    
        def do_something(self):
            bar = 1/0
            return bar + 10
    
    with Sample() as sample:
        sample.do_something()
    复制代码

    这个例子中,wilt后面的get_sample()变成了Sample().这没有任何关系.只要紧跟with后面的语句所返回的对象有__enter__()和__exit__()方法即可,此例中,Sample()的__enter__()方法返回新创建的Sample对象,并赋值给变量sample.

    代码执行后:

    复制代码
    type:  <class 'ZeroDivisionError'>
    value:  division by zero
    trace:  <traceback object at 0x00000192D8305108>
    Traceback (most recent call last):
      File "D:/数据管理/python全栈开发13期/网络编程/day_39/队列.py", line 164, in <module>
        sample.do_something()
      File "D:/数据管理/python全栈开发13期/网络编程/day_39/队列.py", line 160, in do_something
        bar = 1/0
    ZeroDivisionError: division by zero
    复制代码

    实际上,在with后面的代码块抛出任何异常时,__exit__()方法被执行.正如例子所示,异常抛出时,与之关联的type,value和trace传给__exit__()方法,因此判处的ZeroDivisionError异常被打印出来了.开发库,清理资源,关闭文件等等操作,都可以放在__exit__()方法当中.

    因此,Python的with语句时提供了一个有效的机制,让代码更简练,同时在异常产生时,清理工作更简单.

    自定义

    with语句后面的对象必须要有__enter__和__exit__方法,如下:

    复制代码
    class WithTest():
        def __init__(self, name):
            self.name = name
    
        def __enter__(self):
            print("This is enter function", type(self))
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("Now you are exit")
    
        def playNow(self):
            print("now i am playing")
    
    
    with WithTest("chenrun") as test:   # 类中的__enter__方法,将self也就是对象返回并赋值给test
        print("test: ",type(test))
        test.playNow()
        print(test.name)
    复制代码
    运行结果:
    This is enter function <class '__main__.WithTest'> test: <class '__main__.WithTest'> now i am playing chenrun Now you are exit

    自定义的类WithTest,重载了__enter__和__exit__函数,就可以实现with这样的语法了,注意在__enter__函数中,返回了self,在__exit__函数中,可以通过__exit__的返回值来指示with-block部分发生的异常时候需要reraise,如果返回false,则会reraise with block异常,如果返回ture,则就像是什么也没发生.

    上下文管理contextlib模块对with - as的支持

    contexlib模块提供了3个对象: 装饰器contextmanager,函数nested和上下文管理closing,使用这些对象,可以对已有的生成器函数或者对象进行包装,加入对上下文管理协议的支持,避免了专门编写上下文管理器来支持with语句.

    以contextlib的closing来说,closing帮助实现了__enter__和__exit__方法,用户不需要自己在实现这两个方法,但时被closing封装的对象必须提供close方法.contextlib.closing类的实现代码如下:

    复制代码
    class closing():
        def __init__(self, thing):
            self.thing = thing
            
        def __enter__(self):
            return self.thing
        
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.thing.close()
    复制代码

    还可以进行异常的监控和处理,注意后面几个参数,要跳过一个异常,只需要返回该函数True即可,下面这个代码就跳过了所有的TypeError,而让其他异常正常抛出

    def __exit__(self, type, value, traceback):
        return isinstance(value, TypeError)

    总之,with-as表达式极大的简化了每次写finally的工作,这对保持代码优雅性有极大的帮助的.

  • 相关阅读:
    算法训练 P1103
    算法训练 表达式计算
    算法训练 表达式计算
    基础练习 时间转换
    基础练习 字符串对比
    Codeforces 527D Clique Problem
    Codeforces 527C Glass Carving
    Codeforces 527B Error Correct System
    Codeforces 527A Glass Carving
    Topcoder SRM 655 DIV1 250 CountryGroupHard
  • 原文地址:https://www.cnblogs.com/cainingning/p/9374458.html
Copyright © 2011-2022 走看看