python __enter__ 与 __exit__的作用,以及与 with 语句的关系
创始人
2024-06-01 03:04:12
0

With语句是什么?

有一些任务,可能事先需要设置,事后做清理工作。对于这种场景,Python的with语句提供了一种非常方便的处理方式。一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。

如果不用with语句,代码如下:

file = open("/tmp/foo.txt")
data = file.read()
file.close()

这里有两个问题。一是可能忘记关闭文件句柄;二是文件读取数据发生异常,没有进行任何处理。下面是处理异常的加强版本:

file = open("/tmp/foo.txt")
try:data = file.read()
finally:file.close()

虽然这段代码运行良好,但是太冗长了。这时候就是with一展身手的时候了。除了有更优雅的语法,with还可以很好的处理上下文环境产生的异常。下面是with版本的代码:

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

with如何工作?

这看起来充满魔法,但不仅仅是魔法,Python对with的处理还很聪明。基本思想是with所求值的对象必须有一个__enter__()方法,一个__exit__()方法。

紧跟with后面的语句被求值后,返回对象的__enter__()方法被调用,这个方法的返回值将被赋值给as后面的变量。当with后面的代码块全部被执行完之后,将调用前面返回对象的__exit__()方法。

下面例子可以具体说明with如何工作:

#!/usr/bin/env python
# with_example01.pyclass Sample:def __enter__(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

输出如下

bash-3.2$ ./with_example01.py
In __enter__()
sample: Foo
In __exit__()

正如你看到的,

enter()方法被执行
enter()方法返回的值 - 这个例子中是"Foo",赋值给变量’sample’
执行代码块,打印变量"sample"的值为 “Foo”
exit()方法被调用

with真正强大之处是它可以处理异常。可能你已经注意到Sample类的__exit__方法有三个参数val,type 和 trace。 这些参数在异常处理中相当有用。我们来改一下代码,看看具体如何工作的。

#!/usr/bin/env python
# with_example02.pyclass Sample:def __enter__(self):return selfdef __exit__(self, type, value, trace):print "type:", typeprint "value:", valueprint "trace:", tracedef do_something(self):bar = 1/0return bar + 10with Sample() as sample:sample.do_something()

这个例子中,with后面的get_sample()变成了Sample()。这没有任何关系,只要紧跟with后面的语句所返回的对象有__enter__()和__exit__()方法即可。此例中,Sample()的__enter__()方法返回新创建的Sample对象,并赋值给变量sample。

代码执行后:

bash-3.2$ ./with_example02.py
type: 
value: integer division or modulo by zero
trace: 
Traceback (most recent call last):File "./with_example02.py", line 19, in sample.do_somet hing()File "./with_example02.py", line 15, in do_somethingbar = 1/0
ZeroDivisionError: integer division or modulo by zero

实际上,在with后面的代码块抛出任何异常时,exit()方法被执行。正如例子所示,异常抛出时,与之关联的type,value和stack trace传给__exit__()方法,因此抛出的ZeroDivisionError异常被打印出来了。开发库时,清理资源,关闭文件等等操作,都可以放在__exit__方法当中。

因此,Python的with语句是提供一个有效的机制,让代码更简练,同时在异常产生时,清理工作更简单。

原文链接:https://blog.csdn.net/xc_zhou/article/details/80810111

相关内容

热门资讯

定制系统数据安卓转苹果,体验跨... 你有没有想过,手机从安卓转到苹果,这中间的数据迁移,是不是就像搬家一样,既繁琐又让人头疼?别急,今天...
iphone怎么刷安卓双系统 你有没有想过,你的iPhone也能变身成为安卓双系统的小能手呢?没错,就是那个我们平时用来打电话、刷...
安卓系统网络拦截怎么设置,轻松... 你有没有遇到过这种情况:在使用安卓手机时,突然弹出一个广告,让你忍不住想关掉它?或者有时候,一些不安...
苹果系统和安卓系统的区别ppt... 你有没有想过,为什么你的手机里装的是苹果系统而不是安卓系统呢?是不是好奇它们之间有什么不一样的地方?...
安卓系统隐藏运行程序 你知道吗?手机里那些看似安静的小程序,其实可能正在偷偷地运行着呢!是不是觉得有点不可思议?别急,让我...
安卓设置系统简体与繁体,探索安... 亲爱的手机控们,你是否在某个瞬间,突然对手机上的文字产生了好奇,想要知道如何轻松切换安卓系统中的简体...
平凉综合办公系统安卓,便捷高效... 你有没有听说过那个超级方便的平凉综合办公系统安卓版?没错,就是那个能让你的工作生活变得更加轻松的神奇...
安卓系统的实验报告,深入剖析与... 你知道吗?最近我在手机上做了一场有趣的实验,就是测试安卓系统的性能。这可不是随便玩玩,而是真的深入研...
oppo安卓9系统如何,功能亮... 你有没有发现,你的OPPO手机最近是不是有点儿不一样了?是不是觉得它变得更加聪明、更加流畅了呢?哈哈...
苹果装安卓系统卡吗 你有没有想过,把苹果手机换成安卓系统,是不是就像换了个新世界?不过,听说有人担心,苹果装上安卓系统会...
rog安卓10系统键盘下面,键... 亲爱的读者,你是否曾在使用安卓手机时,对那小小的键盘下面隐藏的神秘世界感到好奇?今天,就让我带你一探...
618推荐手机安卓系统 618购物节又要来了!是不是已经迫不及待想要换一部新手机了呢?别急,今天我就要给你推荐几款在安卓系统...
4寸手机安卓系统吗 你有没有想过,为什么现在的手机屏幕越来越小,却依然能塞进那么多的功能呢?今天,我们就来聊聊这个话题:...
安卓系统开启后台程序,高效管理... 你有没有发现,手机里的安卓系统越来越智能了?它就像一个贴心的管家,默默地在后台为你打理着各种事务。但...
战地1内存和安卓系统,战地1内... 你有没有发现,最近玩《战地1》的小伙伴们都在抱怨内存不够用?别急,让我来给你详细解析一下这个问题,顺...
电脑连接安卓系统手机,探索跨平... 你有没有想过,你的电脑和安卓手机之间也能来个亲密接触呢?没错,就是那种无缝连接的感觉,让你的手机屏幕...
安卓系统和ios系统玩吃鸡 你有没有发现,最近不管是大街小巷,还是线上线下的聚会,提到最多的游戏就是“吃鸡”啦!这款游戏可谓是风...
阻止安卓系统杀程序,如何有效阻... 你有没有遇到过这种情况?手机里装了好多喜欢的应用,可是一不小心,某个程序就被安卓系统无情地杀掉了。别...
国内安卓系统大小对比图,国内安... 你有没有想过,我们每天使用的安卓系统,其实就像是一个庞大的“城市”,里面住着各种各样的“居民”,而这...
苹果和安卓系统大小,系统规模对... 你有没有想过,为什么你的手机里装了那么多应用,可内存还是不够用呢?今天,就让我带你一探究竟,揭秘苹果...