python中的with语句使用于对资源进行访问的场合,保证不管处理过程中是否发生错误或者异常都会执行规定的__exit__(“清理”)操作,释放被访问的资源,比如有文件读写后自动关闭、线程中锁的自动获取和释放等。
与python中with语句有关的概念有:上下文管理协议、上下文管理器、运行时上下文、上下文表达式、处理资源的代码段。
with语句的应用场景
编程中有很多操作都是配套使用的,这种配套的流程可以称为计算过程,Python语言为这种计算过程专门设计了一种结构:with语句。比如文件处理就是这类计算过程的典型代表。
使用with语句前后对比
没有使用with语句之前,我们是这样打开一个文件的:
try: # 1. [进入] f = open('a.txt', 'r', encoding="utf-8") # 2. [执行] print(f.read()) finally: if f: # 3. [退出] f.close()
python操作文件的流程一般就是这三步:
1.[进入]用只读方式打开文件
如果文件不存在,open()函数就会抛出一个IOError的错误,并且给出错误码和详细的信息告诉你文件不存在
2.[执行]读取文件内容
如果文件打开成功,接下来,调用read()方法可以一次读取文件的全部内容,Python把内容读到内存,用一个str对象表示
3.[退出]关闭打开的文件
文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的
思考为什么关闭文件操作一定要放在finallly语句里?
由于文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用。所以,为了保证无论是否出错都能正确地关闭文件,我们可以使用try ... finally来实现。
发现共性:
我们发现其实这种过程化的语句有共性,比如说在进去一个片段前必须做某种超赞,处理工作后又需要执行一个结束操作。比如上面的这段代码:
finally: if f: f.close()
就可以做一个封装。
使用with语句后,我们是这样打开一个文件的:
with open("a.txt", "r", encoding="utf-8") as f: print(f.read())
这个with语句和前面的try ... finally结构是一样的,但是代码更佳简洁,并且不必调用f.close()方法。
with语句的执行原理
从解释器的角度去理解with语句执行流程。
with语句的基本形式是:
with 表达式 as 变量: 语句块
这样的一段代码可以称为一个上下文(context),在执行with语句时,解释器会先求出表达式的值,这个值(对象)是一个上下文管理器,并且假设这个对象拥有如下类的构造方法:
def __enter__(): # 描述进入上下文的动作 pass def __exit__(): # 描述退出上下文的动作 pass
with语句在求出这个上下文管理器对象之后,自动执行进入方法,并将这个对象的返回值赋值于 as 之后的变量,然后执行语句块。然后在退出上下文前,自动执行对象的退出方法。
python系统和标准库的一些类型定义了这对操作,可以直接用于with语句。比如文件对象就直接支持这一对操作,因此可以用在with语句的头部。
如果你也有类似的计算过程需要抽取出来,那么可以自定义一个类,并且包含进入、退出方法。
自定义open函数
自己实现才发现,使用装饰器和生成器就能很好的解决这个问题,不需要用到类构造方法来实现;
import contextlib # 引入上下文管理包 @contextlib.contextmanager # 给函数引入装饰器 def myopen(dir, mode): print("开始") f = open(dir, mode, encoding='utf-8') try: # 上文 yield f finally: # 下文 print("结束") f.close() with myopen("a.txt", 'r') as fobj: # 把try中的yield中的f赋值给fobj # with会将with后面的函数中的yield赋值给fobj for i in fobj: print(i) # 等待上面的循环结束后,才最终执行finally的代码,所以这就是上下文管理
输出:
开始 hello,我是a.txt的第1行文字。 结束
总结
打开文件读写、用pickle包完成数据的存储、恢复的操作,都非常适合使用with语句。
pickle包的使用案例:
try: with open("phone.pickle", "wb") as outf: pickle.dump("13193388105", outf) except: print("file have errow.") try: with open("phone.pickle", "rb") as outf: data = pickle.load(outf) print(type(data)) print(data) except: print("file have errow.")
我总结了一下使用with语句的优点:
总结
以上所述是小编给大家介绍的Python with语句和过程抽取思想,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对小牛知识库网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
本文向大家介绍随机抽取的sql语句 每班任意抽取3名学生,包括了随机抽取的sql语句 每班任意抽取3名学生的使用技巧和注意事项,需要的朋友参考一下 学校有一、二、三。。。。至十班。 假设每个班上有30名学生。张、李、刘、苏等 现有这样的表 student ,字段 class 及name 。其中class 表示班级,name 表示每班学生姓名。 要求每班任意抽取3名学生出来,进行学校大扫除。 请写出
语句和语句块是 TJS2 语法中非常重要的元素。 语句 一个语句以 ; (分号) 结束。可以是表达式后直接加分号,也可以是 if 等控制语句后加分号。 例: a++; func1(); returna+b; 等等…… 语句块 语句块由多个语句组成,用{ }括起来表示。语句块中的语句按由上至下的顺序执行。 例: { a++; b++; } { vart=func1(); func2(t); b
本文向大家介绍MySQL查询语句过程和EXPLAIN语句基本概念及其优化,包括了MySQL查询语句过程和EXPLAIN语句基本概念及其优化的使用技巧和注意事项,需要的朋友参考一下 网站或服务的性能关键点很大程度在于数据库的设计(假设你选择了合适的语言开发框架)以及如何查询数据上。 我们知道MySQL的性能优化方法,一般有建立索引、规避复杂联合查询、设置冗余字段、建立中间表、查询缓存等,也知道用EX
着色器语言GLSL中关于if语句、for语句的使用,和javascript语言、C语言中的if语句、for语句执行逻辑规则基本一致,这里默认你已经有一定的编程基础,也就不做过多讲解,只是简单说明一下。 单独使用if if(x>100){ gl_FragColor = vec4(1.0,0.0,0.0,1.0);//红色 } if-else形式 bool colorBool; // 根据布尔值
问题内容: 我有一些话题要讨论。我有一个24 s / s的代码片段。是我自己的类,表示类似于的功能。 这是一段代码: 从可读性的角度来看,我有些担心。将其更改为24类并使用多态性更好吗?我不相信这将使我的代码可维护…一方面,这些s很清楚,应该很容易理解,另一方面,s太多了。 我的问题相当笼统,但是我正在用Python编写代码,所以我不能使用。 你怎么看? 更新 : 重要的一点是,并且是构造函数,我
通常都听到别人说,计算机很牛逼,很聪明,其实计算机一点都不聪明,光是你要跟他沟通,都会气 shi 你,聪明的是在写程序的你。 写程序就是跟计算机沟通,告诉它要做什么。 竟然是这样,那么肯定缺少不了一些沟通逻辑。比如你要告诉计算机在什么情况下做什么?或者在哪个时间点做什么? 这都需要用到逻辑判断。这一章节,主要就是说这个。 目录