python中的with语句

来源:互联网 发布:大数据出现的问题 编辑:程序博客网 时间:2024/06/01 09:57

一:with语句的作用


  with语句是用来调用上下文管理器的,没有上下文管理器就没有with。


二:什么是上下文管理器


  上下文管理器是一种对象,这种对象包含了两个方法:__enter__()__exit__(),当调用上下文管理器时会执行__enter__()方法并把__enter__()的返回值赋给as子句的变量(如果有的话),而with语句体执行结束后或出错时会调用__exit__()方法。

三:with语句的语法格式以及原理 


with 语句的语法格式如下:

1
2
with context_expression [as target(s)]:
    with-body

这里 context_expression 要返回一个上下文管理器对象,该对象并不赋值给 as 子句中的 target(s) ,如果指定了 as 子句的话,会将上下文管理器的 __enter__() 方法的返回值赋值给 target(s)。target(s) 可以是单个变量,或者由“()”括起来的元组(不能是仅仅由“,”分隔的变量列表,必须加“()”)。


四:实现一个上下文管理器


  要实现一个上下文管理器,就是要实现__enter__()和__exit__()这两个方法,这两个方法的定义如下:

  • context_manager.__enter__() :进入上下文管理器的运行时上下文,在语句体执行前调用。with 语句将该方法的返回值赋值给 as 子句中的 target,如果指定了 as 子句的话
  • context_manager.__exit__(exc_type, exc_value, exc_traceback) :退出与上下文管理器相关的运行时上下文,返回一个布尔值表示是否对发生的异常进行处理。参数表示引起退出操作的异常,如果退出时没有发生异常,则3个参数都为None。如果发生异常,返回

    (1)实现一个最简单的上下文管理器:

    class test_with:def __enter__(self):print('in entry')def __exit__(self, *args):print('in exit')with test_with():print('in with statment')

      在这个上下文管理器中实现了两个方法,没有使用as子句,__exit__()方法没有接受参数,没有实现__init__()方法。运行结果:

    create one test_with objectin entryin with statmentin exit

    (2)向上下文管理器中添加内容,实现一个简单的除法。

    class div:    def __init__(self, num1, num2):        self.num1 = num1        self.num2 = num2        self.res = num1 / num2class test_with:    def __init__(self, num1, num2):        self.str = 'one test_with object'        print('in init, create {}'.format(self.str))        self.num1 = num1        self.num2 = num2    def __enter__(self):        print('in entry')        if self.num2 == 0:            raise Exception        div_obj = div(self.num1, self.num2)        return div_obj    def __exit__(self, exc_type, exc_value, exc_traceback):        print('in exit')        if exc_tracebackb is not None:            print('Error!')            return False        else:            print('Success!')with test_with(2, 1) as div_obj:    print('in with statment')    print('{} / {} = {}'.format(        div_obj.num1, div_obj.num2, div_obj.res))with test_with(2, 1) as div_obj:    print('in with statment')    raise Exception    print('{} / {} = {}'.format(        div_obj.num1, div_obj.num2, div_obj.res))
    执行了两次,第二次执行时在with语句体中抛出一个错误

    运行结果:

    in init, create one test_with objectin entryin with statment2 / 1 = 2in exitSuccess!in init, create one test_with objectin entryin with statmentin exitError!Traceback (most recent call last):  File "test_with.py", line 39, in <module>    raise ExceptionException
    两次执行后都会调用__exit__()方法。说明发生异常之后正确的进行了处理。

    五:__exit__()方法的参数与返回值

    (1)参数

      参数表示引起退出操作的异常,如果退出时没有发生异常,则3个参数都为None。type时异常的类型,value是异常的值,traceback是异常的位置。

    (2)返回值

      __exit__()方法可以有返回值,表示是否对异常进行另外处理(或表示__exit__方法是否已经处理异常),若无返回值,则会默认为False,会在退出该方法后重新抛出异常由with之外的语句进行异常处理。若返回值为True,则不会对异常进行处理,不会出现上面执行时的Traceback的报错信息。


    参考文章:https://www.ibm.com/developerworks/cn/opensource/os-cn-pythonwith/

  • 原创粉丝点击