博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
浅谈Python中with(上下文管理器)的用法
阅读量:4921 次
发布时间:2019-06-11

本文共 2285 字,大约阅读时间需要 7 分钟。

例子一

首先来看一段代码:

class Foo(object):    def __init__(self):        print('实例化一个对象')    def __enter__(self):        print('进入')    def __exit__(self, exc_type, exc_val, exc_tb):        print('退出')obj = Foo()with obj:    print('正在执行')

上面代码执行结果为:

实例化一个对象进入正在执行退出

结论1

我们知道,实例化Foo,得到obj对象,会执行Foo的__init__方法,也就是打印了第一句;

按照,程序从上至下执行,应该会打印“正在执行”才对,为什么会在它之前先打印了进入,在它之后打印了退出呢?

 

因为我们在定义Foo时,定义了__enter__和__exit__方法,那么我们实例化的对象obj就是一个上下文管理器,

含有__enter__和__exit__方法的对象就是上下文管理器。

with 上下文管理器:     语句体

当with遇到上下文管理器,就会在执行语句体之前,先执行上下文管理器的__enter__方法,然后再执行语句体,执行完语句体后,最后执行__exit__方法

 

这也就是为什么会出现文章开头的情况的原因。

例子二

再看看这段代码:

class Foo(object):    def __init__(self):        print('实例化一个对象')    def __enter__(self):        print('进入')    def __exit__(self, exc_type, exc_val, exc_tb):        print('退出')     # return Trueobj = Foo()with obj:    raise ImportError    print('正在执行')

结果如下:

 把上面代码中我们注释掉的那一行代码取消注释,结果如下

 

 我们会发现,虽然我们故意在语句体中抛出一个错误,按照正常情况,执行到报错地方就不会执行了,而__exit__是在语句体执行完之后执行的,但还是执行了__exit__方法;当我们在__exit__中给一个返回值为Ture时,就会忽略错误。

 

结论2

所有我们可以发现

with语句类似

  try :

  except:

  finally:

的功能:但是with语句更简洁。而且更安全。代码量更少。

   出现异常时,如果 __exit__ 返回 False(默认不写返回值时,即为False),则会重新抛出异常,让with 之外的语句逻辑来处理异常,这也是通用做法;如果返回 True,则忽略异常,不再对异常进行处理

例子三

class Foo(object):    def __init__(self):        print('实例化一个对象')    def __enter__(self):        print('进入')        # return self    def __exit__(self, exc_type, exc_val, exc_tb):        print('退出')with Foo() as obj:    print(obj,type(obj))    print('正在执行')

把上面代码中我们注释掉的那一行代码取消注释,结果如下

结论

调用上下文管理器的 __enter__ 方法时;如果使用了 as 子句,则将 __enter__() 方法的返回值赋值给 as 子句中的目标

with 上下文管理器  as  target:    代码语句体

with后面必须跟一个上下文管理器,如果使用了as,则是把上下文管理器的 __enter__() 方法的返回值赋值给 target,target 可以是单个变量,或者由“()”括起来的元组(不能是仅仅由“,”分隔的变量列表,必须加“()”)

例子四

我们经常会看到这样的代码:

with open("/tmp/foo.txt") as file:    data = file.read()

 结论

这里使用了 with 语句,不管在处理文件过程中是否发生异常,都能保证 with 语句执行完毕后已经关闭了打开的文件句柄。如果使用传统的 try/finally 范式,则要使用类似如下代码:

somefile = open(r'somefileName')try:    for line in somefile:        print line        # ...more codefinally:    somefile.close()

比较起来,使用 with 语句可以减少编码量。已经加入对上下文管理协议支持的还有模块 threading、decimal 等。

补充

with只能配合上下文管理器使用,常见的上下文管理器有

filedecimal.Contextthread.LockTypethreading.Lockthreading.RLockthreading.Conditionthreading.Semaphorethreading.BoundedSemaphore

 

转载于:https://www.cnblogs.com/gwklan/p/11140059.html

你可能感兴趣的文章
.net core 使用阿里云短信发送SMS
查看>>
Unity5.1 新的网络引擎UNET(四) UNET Remote Actions
查看>>
How to get service execuable path
查看>>
39岁了,我依旧要谈梦想
查看>>
java的IO流初探
查看>>
反射实现java深度克隆
查看>>
转载 Javascript DOM Document|Element|Attribute对象方法详解
查看>>
图书助手冲刺第六天
查看>>
需求评审
查看>>
Calculate the distance between two lines in 3D space
查看>>
观察者模式(发布-订阅模式)
查看>>
JavaScript 中 类型转换
查看>>
HDU 1069 Monkey and Banana(DP)
查看>>
HDU 2577 How to Type(杭电300题纪念)
查看>>
TestNG中的DataProvider返回Iterator<Object[]>的妙用
查看>>
WebApi使用二进制方式上传和下载文件
查看>>
CS224n学习笔记(二)
查看>>
pymysql模块
查看>>
ThreadLocal
查看>>
安全需求-建模归类——By Me
查看>>