python中的with语句

一: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 object
    in entry
    in with statment
    in exit

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

    class div:
        def __init__(self, num1, num2):
            self.num1 = num1
            self.num2 = num2
            self.res = num1 / num2
    
    
    class 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 object
    in entry
    in with statment
    2 / 1 = 2
    in exit
    Success!
    in init, create one test_with object
    in entry
    in with statment
    in exit
    Error!
    Traceback (most recent call last):
      File "test_with.py", line 39, in <module>
        raise Exception
    Exception
    两次执行后都会调用__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/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值