python的with用法(转载)
原文地址:https://www.cnblogs.com/wanglei-xiaoshitou1/p/9238275.html
一、with语句是什么?
有一些任务,可能事先需要设置,事后做清理工作。对于这种场景,Python的with语句提供了一种非常方便的处理方式。一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。
如果不用with语句,代码如下:
file = open("/tmp/foo.txt")
data = file.read()
file.close()
这里有两个问题:
一是可能忘记关闭文件句柄;
二是文件读取数据发生异常,没有进行任何处理。
下面是处理异常的加强版本:
try:
f = open('xxx')
except:
print 'fail to open'
exit(-1)
try:
do something
except:
do something
finally:
f.close()
虽然这段代码运行良好,但是太冗长了。
这时候就是with一展身手的时候了。除了有更优雅的语法,with还可以很好的处理上下文环境产生的异常。
下面是with版本的代码:
with open("/tmp/foo.txt") as file:
data = file.read()
-----------------------------------------------------------------------------------------------------------------------------
二、with如何工作?
紧跟with后面的语句被求值后,返回对象的 __enter__() 方法被调用,这个方法的返回值将被赋值给as后面的变量。
当with后面的代码块全部被执行完之后,将调用前面返回对象的 __exit__()方法。
下面例子可以具体说明with如何工作:
#!/usr/bin/env python
# with_example01.py
class 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__()
正如你看到的: 1. __enter__()方法被执行 2. __enter__()方法返回的值 - 这个例子中是”Foo”,赋值给变量’sample’ 3. 执行代码块,打印变量”sample”的值为 “Foo” 4. __exit__()方法被调用
with真正强大之处是它可以处理异常。可能你已经注意到Sample类的 __exit__ 方法有三个参数 val, type 和 trace。 这些参数在异常处理中相当有用。我们来改一下代码,看看具体如何工作的。
#!/usr/bin/env python
# with_example02.py class Sample:
def __enter__(self):
return self
def __exit__(self, type, value, trace):
print "type:", type
print "value:", value
print "trace:", trace
def do_something(self):
bar = 1/0
return bar + 10
with Sample() as sample:
sample.do_something()
这个例子中,with后面的get_sample()变成了Sample()。这没有任何关系,只要紧跟with后面的语句所返回的对象有 __enter__() 和 __exit__() 方法即可。此例中,Sample()的 __enter__() 方法返回新创建的Sample对象,并赋值给变量sample。
代码执行后:
bash-3.2$ ./with_example02.py
type: <type 'exceptions.ZeroDivisionError'>
value: integer division or modulo by zero
trace: <traceback object at 0x1004a8128>
Traceback (most recent call last):
File "./with_example02.py", line 19, in <module>
sample.do_something()
File "./with_example02.py", line 15, in do_something
bar = 1/0
ZeroDivisionError: integer division or modulo by zero
实际上,在with后面的代码块抛出任何异常时,__exit__() 方法被执行。正如例子所示,异常抛出时,与之关联的type,value和stack trace传给 __exit__() 方法,因此抛出的ZeroDivisionError异常被打印出来了。开发库时,清理资源,关闭文件等等操作,都可以放在 __exit__ 方法当中。
另外,__exit__ 除了用于tear things down,还可以进行异常的监控和处理,注意后几个参数。要跳过一个异常,只需要返回该函数True即可。
下面的样例代码跳过了所有的TypeError,而让其他异常正常抛出。
def __exit__(self, type, value, traceback):
return isinstance(value, TypeError)
总之,with-as表达式极大的简化了每次写finally的工作,这对保持代码的优雅性是有极大帮助的。
如果有多个项,我们可以这么写:
with open("x.txt") as f1, open('xxx.txt') as f2:
do something with f1,f2
因此,Python的with语句是提供一个有效的机制,让代码更简练,同时在异常产生时,清理工作更简单。
三、相关术语
要使用 with 语句,首先要明白上下文管理器这一概念。有了上下文管理器,with 语句才能工作。
下面是一组与上下文管理器和with 语句有关的概念。
上下文管理协议(Context Management Protocol):包含方法 __enter__() 和 __exit__(),支持该协议的对象要实现这两个方法。
上下文管理器(Context
Manager):支持上下文管理协议的对象,这种对象实现了__enter__() 和 __exit__() 方法。上下文管理器定义执行
with 语句时要建立的运行时上下文,负责执行 with 语句块上下文中的进入与退出操作。通常使用 with
语句调用上下文管理器,也可以通过直接调用其方法来使用。
运行时上下文(runtime
context):由上下文管理器创建,通过上下文管理器的 __enter__() 和__exit__() 方法实现,__enter__()
方法在语句体执行之前进入运行时上下文,__exit__() 在语句体执行完后从运行时上下文退出。with 语句支持运行时上下文这一概念。
上下文表达式(Context Expression):with 语句中跟在关键字 with 之后的表达式,该表达式要返回一个上下文管理器对象。
语句体(with-body):with 语句包裹起来的代码块,在执行语句体之前会调用上下文管理器的 __enter__() 方法,执行完语句体之后会执行__exit__() 方法。
python的with用法(转载)的更多相关文章
- Python回调函数用法实例详解
本文实例讲述了Python回调函数用法.分享给大家供大家参考.具体分析如下: 一.百度百科上对回调函数的解释: 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函 ...
- python map 常见用法
python map 常见用法2017年02月01日 19:32:41 淇怪君 阅读数:548版权声明:欢迎转载,转载请注明出处 https://blog.csdn.net/Tifficial/art ...
- Python高阶用法总结
目录 1. lambda匿名函数 1.1 函数式编程 1.2 应用在闭包 2. 列表解析式 3. enumerate内建函数 4. 迭代器与生成器 4.1 迭代器 4.3 生成器 5. 装饰器 前言: ...
- python操作redis用法详解
python操作redis用法详解 转载地址 1.redis连接 redis提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用 ...
- day01-day04总结- Python 数据类型及其用法
Python 数据类型及其用法: 本文总结一下Python中用到的各种数据类型,以及如何使用可以使得我们的代码变得简洁. 基本结构 我们首先要看的是几乎任何语言都具有的数据类型,包括字符串.整型.浮点 ...
- 【Python】关于Python有意思的用法
开一篇文章,记录关于Python有意思的用法,不断更新 1.Python树的遍历 def sum(t): tmp=0 for k in t: if not isinstance(k,list): tm ...
- python中xrange用法分析
本文实例讲述了python中xrange用法.分享给大家供大家参考.具体如下: 先来看如下示例: >>> x=xrange(0,8) >>> print x xra ...
- 浅谈Python在信息学竞赛中的运用及Python的基本用法
浅谈Python在信息学竞赛中的运用及Python的基本用法 前言 众所周知,Python是一种非常实用的语言.但是由于其运算时的低效和解释型编译,在信息学竞赛中并不用于完成算法程序.但正如LRJ在& ...
- python scapy的用法之ARP主机扫描和ARP欺骗
python scapy的用法之ARP主机扫描和ARP欺骗 目录: 1.scapy介绍 2.安装scapy 3.scapy常用 4.ARP主机扫描 5.ARP欺骗 一.scapy介绍 scapy是一个 ...
- python函数的用法
python函数的用法 目录: 1.定义.使用函数 1.函数定义:def 2.函数调用:例:myprint() 3.函数可以当作一个值赋值给一个变量 例:a=myprint() a() 4.写r ...
随机推荐
- Go - 实现项目内链路追踪
为什么项目内需要链路追踪?当一个请求中,请求了多个服务单元,如果请求出现了错误或异常,很难去定位是哪个服务出了问题,这时就需要链路追踪. 从图中可以清晰的看出他们之间的调用关系,通过一个例子说明下链路 ...
- C++类基本--随笔二
1 #include <iostream> 2 #include <string.h> 3 using namespace std; 4 5 class Internet 6 ...
- H3C交换机DHCP配置
1.dhcp配置 dhcp enable:开启dhcp功能 dhcp server forbidden-ip 10.1.130.2 10.1.130.10----排除dhcp的一些地址 dhcp se ...
- 32.vsftpd服务程序--匿名开放模式
1.vsftpd服务程序 vsftpd 作为更加安全的文件传输的服务程序,允许用户以三种认证模式登录到FTP 服务器上. 匿名开放模式:是一种最不安全的认证模式,任何人都可以无需密码验证而直接登录到F ...
- Flink-v1.12官方网站翻译-P027-State Schema Evolution
状态方案的演变 Apache Flink流媒体应用通常被设计为无限期或长时间运行.与所有长期运行的服务一样,应用程序需要更新以适应不断变化的需求.这对于应用程序所针对的数据模式也是一样的,它们会随着应 ...
- 配置VS2013 + opencv 2.4.10
其实我内心是极力反对装这么老的版本的,但是要交课堂作业~~好无奈 [注] : 如果按照本文配置不成功,可以试一下其他博客里面的配置(多试一试总能成功的) https://jingyan.baidu.c ...
- - 迷宫问题 POJ - 3984 bfs记录路径并输出最短路径
定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, ...
- CF1465-C. Peaceful Rooks
CF1465-C. Peaceful Rooks 预备小知识: Rook(国际象棋中的车). 国际象棋中的棋子.每人有2个,他只能直走,不能斜走,除王车易位外不能越子. -- 来自<百度百科&g ...
- CF1466-D. 13th Labour of Heracles
CF1466-D. 13th Labour of Heracles 题意: 给出一个由\(n\)个点构成的树,每个点都有一个权值.现在你可以用\(k,k\subset\)\([1, n]\)个颜色来给 ...
- Linux-字符处理命令
目录 1.sort(排序) 2.uniq(不相邻的两行重复不会去除) 3.cut(取列,截取字段) 4.wc(统计行.单词.字符数) 1.sort(排序) 选项: -t # 指定分隔符 -k # 指定 ...