当前位置:   article > 正文

Python 中 with用法及原理_python with 实现原理

python with 实现原理

前言

with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭/线程中锁的自动获取和释放等。

问题引出

如下代码:

  1. file = open("1.txt")
  2. data = file.read()
  3. file.close()

上面代码存在2个问题: 
(1)文件读取发生异常,但没有进行任何处理; 
(2)可能忘记关闭文件句柄;

改进

  1. try:
  2. f = open('xxx')
  3. except:
  4. print('fail to open')
  5. exit(-1)
  6. try:
  7. do something
  8. except:
  9. do something
  10. finally:
  11. f.close()

虽然这段代码运行良好,但比较冗长。 
而使用with的话,能够减少冗长,还能自动处理上下文环境产生的异常。如下面代码:

  1. with open("1.txt") as file:
  2. data = file.read()

with 工作原理

(1)紧跟with后面的语句被求值后,返回对象的“__ enter__()”方法被调用,这个方法的返回值将被赋值给as后面的变量; 
(2)当with后面的代码块全部被执行完之后,将调用前面返回对象的“__exit__()”方法。 
with工作原理代码示例:
  1. class Sample:
  2. def __enter__(self):
  3. print "in __enter__"
  4. return "Foo"
  5. def __exit__(self, exc_type, exc_val, exc_tb):
  6. print "in __exit__"
  7. def get_sample():
  8. return Sample()
  9. with get_sample() as sample:
  10. print "Sample: ", sample

代码的运行结果如下:

  1. in __enter__
  2. Sample: Foo
  3. in __exit__

可以看到,整个运行过程如下: 
(1)__enter__()方法被执行; 
(2)__enter__()方法返回的值,在这个例子中是”Foo”,赋值给变量sample; 
(3)执行代码块,打印sample变量的值为”Foo”; 
(4)__exit__()方法被调用;

【注:】__exit__方法中有3个参数, exc_type, exc_val, exc_tb,这些参数在异常处理中相当有用。 
exc_type: 错误的类型 
exc_val: 错误类型对应的值 
exc_tb: 代码中错误发生的位置 
示例代码:

  1. class Sample():
  2. def __enter__(self):
  3. print('in enter')
  4. return self
  5. def __exit__(self, exc_type, exc_val, exc_tb):
  6. print "type: ", exc_type
  7. print "val: ", exc_val
  8. print "tb: ", exc_tb
  9. def do_something(self):
  10. bar = 1 / 0
  11. return bar + 10
  12. with Sample() as sample:
  13. sample.do_something()

程序输出结果:

  1. in enter
  2. Traceback (most recent call last):
  3. type: <type 'exceptions.ZeroDivisionError'>
  4. val: integer division or modulo by zero
  5. File "/home/user/cltdevelop/Code/TF_Practice_2017_06_06/with_test.py", line 36, in <module>
  6. tb: <traceback object at 0x7f9e13fc6050>
  7. sample.do_something()
  8. File "/home/user/cltdevelop/Code/TF_Practice_2017_06_06/with_test.py", line 32, in do_something
  9. bar = 1 / 0
  10. ZeroDivisionError: integer division or modulo by zero
  11. Process finished with exit code 1

总结

实际上,在with后面的代码块抛出异常时,exit()方法被执行。开发库时,清理资源,关闭文件等操作,都可以放在exit()方法中。 
总之,with-as表达式极大的简化了每次写finally的工作,这对代码的优雅性是有极大帮助的。 
如果有多项,可以这样写:

  1. With open('1.txt') as f1, open('2.txt') as f2:
  2. do something
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/183133
推荐阅读
相关标签
  

闽ICP备14008679号