with as 如何工作

 

with如何工作?

Python对with的处理还是很机智滴.基本思想就是with所求值的对象必须有一个__enter__()方法,一个__exit__()方法

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

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

class Sample:
def __enter__(self):
print("in __enter__")
return "foo" # 返回值赋值给了"sample",所以下面代码打印的foo def __exit__(self, exc_type, exc_val, exc_tb):
print("in __exit__()") def get_sample():
return Sample() with get_sample() as sample:
print("sample", sample)

运行代码,输出如下

in __enter__
sample foo
in __exit__()

1,__enter__()方法被执行

2,__enter__()方法返回的值 - 这个例子中的"foo",赋值给变量"sample"

3,执行代码块,打印变量"smple"的值为"foo"

4,__exit__()方法被调用

with真正强大之处是他可以处理异常,可能你已经注意到Sample类的__exit__方法有三个参数

exc_type,exc_val,exc_tb.这些参数在异常处理中相当有用,我们开修改下代码:

class Sample:
def __enter__(self):
return self def __exit__(self, exc_type, exc_val, exc_tb):
print("type: ", exc_type)
print("value: ", exc_val)
print("trace: ", exc_tb) def do_something(self):
bar = 1/0
return bar + 10 with Sample() as sample:
sample.do_something()

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

代码执行后:

type:  <class 'ZeroDivisionError'>
value: division by zero
trace: <traceback object at 0x00000192D8305108>
Traceback (most recent call last):
File "D:/数据管理/python全栈开发13期/网络编程/day_39/队列.py", line 164, in <module>
sample.do_something()
File "D:/数据管理/python全栈开发13期/网络编程/day_39/队列.py", line 160, in do_something
bar = 1/0
ZeroDivisionError: division by zero

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

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

自定义

with语句后面的对象必须要有__enter__和__exit__方法,如下:

class WithTest():
def __init__(self, name):
self.name = name def __enter__(self):
print("This is enter function", type(self))
return self def __exit__(self, exc_type, exc_val, exc_tb):
print("Now you are exit") def playNow(self):
print("now i am playing") with WithTest("chenrun") as test: # 类中的__enter__方法,将self也就是对象返回并赋值给test
print("test: ",type(test))
test.playNow()
print(test.name)
运行结果:
This is enter function <class '__main__.WithTest'>
test: <class '__main__.WithTest'>
now i am playing
chenrun
Now you are exit

自定义的类WithTest,重载了__enter__和__exit__函数,就可以实现with这样的语法了,注意在__enter__函数中,返回了self,在__exit__函数中,可以通过__exit__的返回值来指示with-block部分发生的异常时候需要reraise,如果返回false,则会reraise with block异常,如果返回ture,则就像是什么也没发生.

上下文管理contextlib模块对with - as的支持

contexlib模块提供了3个对象: 装饰器contextmanager,函数nested和上下文管理closing,使用这些对象,可以对已有的生成器函数或者对象进行包装,加入对上下文管理协议的支持,避免了专门编写上下文管理器来支持with语句.

以contextlib的closing来说,closing帮助实现了__enter__和__exit__方法,用户不需要自己在实现这两个方法,但时被closing封装的对象必须提供close方法.contextlib.closing类的实现代码如下:

class closing():
def __init__(self, thing):
self.thing = thing def __enter__(self):
return self.thing def __exit__(self, exc_type, exc_val, exc_tb):
self.thing.close()

还可以进行异常的监控和处理,注意后面几个参数,要跳过一个异常,只需要返回该函数True即可,下面这个代码就跳过了所有的TypeError,而让其他异常正常抛出

def __exit__(self, type, value, traceback):
return isinstance(value, TypeError)

总之,with-as表达式极大的简化了每次写finally的工作,这对保持代码优雅性有极大的帮助的.

with as 如何工作的更多相关文章

  1. ASP.NET是如何在IIS下工作的

    ASP.NET与IIS是紧密联系的,由于IIS6.0与IIS7.0的工作方式的不同,导致ASP.NET的工作原理也发生了相应的变化. IIS6(IIS7的经典模式)与IIS7的集成模式的不同 IIS6 ...

  2. 菜鸟学Struts2——Struts工作原理

    在完成Struts2的HelloWorld后,对Struts2的工作原理进行学习.Struts2框架可以按照模块来划分为Servlet Filters,Struts核心模块,拦截器和用户实现部分,其中 ...

  3. C#中如何在Excel工作表创建混合型图表

    在进行图表分析的时候,我们可能需要在一张图表呈现两个或多个样式的图表,以便更加清晰.直观地查看不同的数据大小和变化趋势.在这篇文章中,我将分享C#中如何在一张图表中创建不同的图表类型,其中包括如何在同 ...

  4. OEL上使用yum install oracle-validated 简化主机配置工作

    环境:OEL 5.7 + Oracle 10.2.0.5 RAC 如果你正在用OEL(Oracle Enterprise Linux)系统部署Oracle,那么可以使用yum安装oracle-vali ...

  5. 通过AngularJS实现前端与后台的数据对接(一)——预备工作篇

    最近,笔者在做一个项目:使用AngularJS,从而实现前端与后台的数据对接.笔者这是第一次做前端与后台的数据对接的工作,因此遇到了许多问题.笔者在这些问题中,总结了一些如何实现前端与后台的数据对接的 ...

  6. 从啥也不会到可以胜任最基本的JavaWeb工作,推荐给新人的学习路线(二)

    在上一节中,主要阐述了JavaScript方面的学习路线.先列举一下我朋友的经历,他去过培训机构,说是4个月后月薪过万,虽然他现在还未达到这个指标. 培训机构一般的套路是这样:先教JavaSE,什么都 ...

  7. Java程序员:工作还是游戏,是该好好衡量一下了

    前阵子我终于下定决心,删掉了硬盘里所有的游戏. 身为一个程序猿,每天都要和各种新技术打交道,闲暇时间,总还得看一下各大论坛,逛逛博客园啥的,给自己充充电.游戏的话,其实我自小就比较喜欢,可以算是一种兴 ...

  8. 【夯实Nginx基础】Nginx工作原理和优化、漏洞

    本文地址 原文地址 本文提纲: 1.  Nginx的模块与工作原理    2.  Nginx的进程模型    3 . NginxFastCGI运行原理        3.1 什么是 FastCGI   ...

  9. HashMap的工作原理

    HashMap的工作原理   HashMap的工作原理是近年来常见的Java面试题.几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道HashTable和HashMap之间 ...

  10. 《CPU的工作过程》

    本文转载自inter官方网址:https://software.intel.com/zh-cn/articles/book-Processor-Architecture_CPU_work_proces ...

随机推荐

  1. 开源 人脸识别 openface 实用介绍 实例演示 训练自己的模型

    1.OpenFace 是 卡耐基梅陇(CMU)大学的一个图像+机器学习项目,整体程序包含:人脸发现,特征提取,特征神经网络训练,人脸识别这四部分. github   https://github.co ...

  2. 35. Oracle监听器启动出错:本地计算机上的OracleOraDb11g_home1TNSListener服务启动后又停止了解决方案

    一.原因分析 你安装oracle的时候是连网的,那么listener.ora文件里的HOST=网络给你分配的IP地址,而在你断网的时候就会出现这样的情况. 三.解决办法 方法一:监听器 通过liste ...

  3. a标签自执行点击事件

    //html <a href='http://www.baidu.com' ><button id='sss'>百度</button></a> //原生 ...

  4. DataBinding(二):DataBinding的基本用法

    转自:DataBinding系列(二):DataBinding的基本用法 1.在xml中引入一些基础变量Variables data 标签中可以有任意数量的 variable 标签.这些变量可以使Ja ...

  5. N的多次方Python实现

    N的多次方描述编写一个程序,计算输入数字N的0次方到5次方结果,并依次输出这6个结果,输出结果间用空格分隔.其中:N是一个整数或浮点数.print()函数可以同时输出多个信息,采用如下方法可以使用空格 ...

  6. Xshell 用鼠标选中一段文字后自动换行

    现象: 使用Xshell连接远程服务器,一般选中都是鼠标选中,然后按快捷键 Ctrl+Insert复制,Shift+Insert粘贴. 可是当选中后松开鼠标,这时候仿佛在xshell里自动输了一个回车 ...

  7. es6 初级之展开运算符

    1.1 先看一个求最大值的例子 <!DOCTYPE html> <html lang="en"> <head> <meta charset ...

  8. oracle第二天笔记

    多表查询 /* 多表查询: 笛卡尔积: 实际上是两张表的乘积,但是在实际开发中没有太大意义 格式: select * from 表1,表2 */ select * from emp; select * ...

  9. How to Pronounce the Numbers 1 – 10

    How to Pronounce the Numbers 1 – 10 Share Tweet Share Tagged With: Numbers Numbers are something you ...

  10. zatree的安装

    zatree的安装有2种 一种是支持2.x的用以下方法安装 zabbix安装zatree 实现图形树状化 官网:https://github.com/spide4k/zatree [root@SERV ...