with as语句的深入探究

with…as语句执行顺序: 
–>首先执行expression里面的__enter__函数,它的返回值会赋给as后面的variable,想让它返回什么就返回什么,只要你知道怎么处理就可以了,如果不写as variable,返回值会被忽略。

–>然后,开始执行with-block中的语句,不论成功失败(比如发生异常、错误,设置sys.exit()),在with-block执行完成后,会执行expression中的__exit__函数。

with...as语句中with-block被执行或者终止后,这个类对象应该做什么。如果这个码块执行成功,则exception_type,exception_valtrace的输入值都是null。如果码块出错了,就会变成像try/except/finally语句一样,exception_typeexception_valtrace 这三个值系统会分配值。


这个和try finally函数有什么关系呢?其实,这样的过程等价于:

try:  
    执行 __enter__的内容  
    执行 with_block.  
finally:  
    执行 __exit__内容 

那么__enter____exit__是怎么用的方法呢?我们直接来看一个栗子好了。 
程序无错的例子:

class Sample(object):             # object类是所有类最终都会继承的类
    def __enter__(self):          # 类中函数第一个参数始终是self,表示创建的实例本身
        print("In __enter__()")
        return "Foo"

    def __exit__(self, type, value, trace):
        print("In __exit__()")


def get_sample():
    return Sample()


with get_sample() as sample:
    print("sample:", sample)


print(Sample)    # 这个表示类本身   <class '__main__.Sample'>
print(Sample())  # 这表示创建了一个匿名实例对象 <__main__.Sample object at 0x00000259369CF550>

 

输出结果:

In __enter__()
sample: Foo
In __exit__()
<class '__main__.Sample'>
<__main__.Sample object at 0x00000226EC5AF550>

 

步骤分析: 
–> 调用get_sample()函数,返回Sample类的实例; 
–> 执行Sample类中的__enter__()方法,打印"In__enter_()"字符串,并将字符串“Foo”赋值给as后面的sample变量; 
–> 执行with-block码块,即打印"sample: %s"字符串,结果为"sample: Foo" 
–> 执行with-block码块结束,返回Sample类,执行类方法__exit__()。因为在执行with-block码块时并没有错误返回,所以type,value,trace这三个arguments都没有值。直接打印"In__exit__()"

程序有错的例子:

class Sample:
    def __enter__(self):
        return self

    def __exit__(self, type, value, trace):
        print("type:", type)
        print("value:", value)
        print("trace:", trace)

    def do_something(self):
        bar = 1 / 0
        return bar + 10


with Sample() as sample:
    sample.do_something()

 

输出结果:

type: <class 'ZeroDivisionError'>
value: division by zero
trace: <traceback object at 0x0000019B73153848>
Traceback (most recent call last):
  File "F:/机器学习/生物信息学/Code/first/hir.py", line 16, in <module>
    sample.do_something()
  File "F:/机器学习/生物信息学/Code/first/hir.py", line 11, in do_something
    bar = 1 / 0
ZeroDivisionError: division by zero

 

步骤分析: 
–> 实例化Sample类,执行类方法__enter__(),返回值self也就是实例自己赋值给sample。即sampleSample的一个实例(对象); 
–>执行with-block码块: 实例sample调用方法do_something()
–>执行do_something()第一行 bar = 1 / 0,发现ZeroDivisionError,直接结束with-block代码块运行 
–>执行类方法__exit__(),带入ZeroDivisionError的错误信息值,也就是type,valuetrace,并打印它们。

posted @ 2020-10-13 22:06  遥月  阅读(171)  评论(0)    收藏  举报