在实际的编码过程中,有时有一些任务,需要事先做一些设置,事后做一些清理,这时就需要python3 with出场了,with能够对这样的需求进行一个比较优雅的处理,最常用的例子就是对访问文件的处理。

文件读写初级:

一般访问文件资源时我们会这样处理:

 f = open(r'c:\mytest.txt', 'r')
data = f.read()
f.close()

存在两个问题:

1. 如果在读写时出现异常而忘了异常处理。
2. 忘了关闭文件句柄

文件读写中级:

以下的加强版本的写法:

  f = open(r'c:\mytest.txt', 'r')
try:
data = f.read()
finally:
f.close()

以上的写法就可以避免因读取文件时异常的发生而没有关闭问题的处理了。代码长了一些。

文件读写高级:

使用with有更优雅的写法:

 with open(r'c:\test.txt', 'r') as f:
data = f.read()

说明:

with后面接的对象返回的结果赋值给f。此例当中open函数返回的文件对象赋值给了f;with会自已获取上下文件的异常信息。

with语句的工作原理

__enter__()/__exit__()这两个方法

with后面返回的对象要求必须有这两个方法,而文件对象f刚好是有这两个方法的。

object.__enter__(self)

进入与此对象相关的运行时上下文。with语句将将此方法的返回值绑定到语句的AS子句中指定的目标(如果有设置的话)

object.__exit__(self, exc_type, exc_value, traceback)

退出与此对象相关的运行时上下文。参数描述导致上下文退出的异常。如果上下文运行时没有异常发生,那么三个参数都将置为None。
如果有异常发生,并且该方法希望抑制异常(即阻止它被传播),则它应该返回True。否则,异常将在退出该方法时正常处理。

注意:

__exit__()方法不应该重新抛出传入的异常,这是调用者的职责。

下面,以3个实例讲解:

1、无异常情况:

 class Test:
    def __enter__(self):
        print('__enter__() is call!')
        return self     def dosomething(self):
        print('dosomethong!')     def __exit__(self, exc_type, exc_value, traceback):
        print('__exit__() is call!')
        print(f'type:{exc_type}')
        print(f'value:{exc_value}')
        print(f'trace:{traceback}')
        print('__exit()__ is call!') with Test() as sample:
    sample.dosomething() >>>__enter__() is call!
>>>dosomethong!
>>>__exit__() is call!
>>>type:None
>>>value:None
>>>trace:None
>>>__exit()__ is call!

以上的实例Text,我们注意到他带有__enter__()/__exit__()这两个方法,当对象被实例化时,就会主动调用__enter__()方法,任务执行完成后就会调用__exit__()方法,另外,注意到,__exit__()方法是带有三个参数的(exc_type, exc_value, traceback), 依据上面的官方说明:如果上下文运行时没有异常发生,那么三个参数都将置为None, 这里三个参数由于没有发生异常,的确是置为了None, 与预期一致。

2、出现并抛出异常:

 class Test:
    def __enter__(self):
        print('__enter__() is call!')
        return self     def dosomething(self):
        x = 1/0
        print('dosomethong!')     def __exit__(self, exc_type, exc_value, traceback):
        print('__exit__() is call!')
        print(f'type:{exc_type}')
        print(f'value:{exc_value}')
        print(f'trace:{traceback}')
        print('__exit()__ is call!')
        # return True with Test() as sample:
    sample.dosomething()
>>>
__enter__() is call!
Traceback (most recent call last):
__exit__() is call!
type:<class 'ZeroDivisionError'>
  File "C:/Users/xxx/PycharmProjects/Test1/test.py", line 23, in <module>
value:division by zero
    sample.dosomething()
trace:<traceback object at 0x000001C08CF32F88>
  File "C:/Users/xxx/PycharmProjects/Test1/test.py", line 10, in dosomething
__exit()__ is call!
    x = 1/0
ZeroDivisionError: division by zero

从结果可以看出, 在执行到dosomethong时就发生了异常,然后将异常传给了__exit__(), 依据上面的官方说明:如果有异常发生,并且该方法希望抑制异常(即阻止它被传播),则它应该返回True。否则,异常将在退出该方法时正常处理。当前__exit__并没有写明返回True,故会抛出异常,也是合理的,但是正常来讲,程序应该是不希望它抛出异常的,这也是调用者的职责,我们将再次修改__exit__, 将其返回设置为True,

3、出现异常,阻止异常抛出:

 class Test:
    def __enter__(self):
        print('__enter__() is call!')
        return self     def dosomething(self):
        x = 1/0
        print('dosomethong!')     def __exit__(self, exc_type, exc_value, traceback):
        print('__exit__() is call!')
        print(f'type:{exc_type}')
        print(f'value:{exc_value}')
        print(f'trace:{traceback}')
        print('__exit()__ is call!')
        return True with Test() as sample:
    sample.dosomething() >>>
__enter__() is call!
__exit__() is call!
type:<class 'ZeroDivisionError'>
value:division by zero
trace:<traceback object at 0x000001C94E592F88>
__exit()__ is call!

从结果看,异常抛出被抑制了,符合预期。

---------------------
本文为CSDN博主「五力」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lxy210781/article/details/81176687

Python3 之 with语句(高效、便捷)的更多相关文章

  1. MySQL语句高效写法整理

    优先使用INNER JOIN 多表关联查询,扫描的行尽量少         关联的时候下条件减少扫描的行数 SELECT     ... FROM     ad_ad_summary_for_pos_ ...

  2. APPLE框架之高效便捷的Repository解决方案

    原文地址:http://perfy315.iteye.com/blog/1460226 Spring Data JPA 转至:http://note.sdo.com/u/855924134/n/P15 ...

  3. Java实现高效便捷还容易懂的排序算法

    PS:我现在越来越认为排序大法是,很深的算法了,就是简单的几个步骤,网上的大佬们能给你玩出花来(ง •_•)ง public class zimuzhenlie2 { public static vo ...

  4. python3之if与语句

    获得更多资料欢迎进入我的网站或者 csdn或者博客园 本节主要介绍python,if条件语句,以及用法.下面附有之前的文章: 语句快介绍 语句快并非一种语句,是通过缩进形成的语句集合: 可以使用的缩进 ...

  5. Javascript之高效编程

    前言: Javascript绝对是最火的编程语言之一,一直具有很大的用户群,具有广泛的应用前景.而在前端开发中,它也是三驾马车之一,并且是最重要的一环.要想给用户提供更流畅的操作体验,更友好的交互,对 ...

  6. Python3分析sitemap.xml抓取导出全站链接

    最近网站从HTTPS转为HTTP,更换了网址,旧网址做了301重定向,折腾有点大,于是在百度站长平台提交网址,不管是主动推送还是手动提交,前提都是要整理网站的链接,手动添加太麻烦,效率低,于是就想写个 ...

  7. python3爬虫_环境安装

    一.环境安装 1.python3安装 官网:https://www.python.org/downloads/ 64 位系统可以下载 Windows x86-64 executable install ...

  8. python2.+进化至python3.+ 语法变动差异(不定期更新)

    1.输出 python2.+ 输出: print "" python3.+ 输出: print ("") 2.打开文件 python2.+ 打开文件: file ...

  9. SQL基本语句的优化10个原则

    原则一:尽量避免在列上进行运算,这样会导致索引失效. 例如: ; 优化: SELECT * FROM table WHERE d >= '2011-01-01'; 原则二:使用JOIN时,应该用 ...

随机推荐

  1. NVDLA中Winograd卷积的设计

    在AI芯片:高性能卷积计算中的数据复用曾提到,基于变换域的卷积计算--譬如Winograd卷积--并不能适应算法上对卷积计算多变的需求.但Winograd卷积依旧出现在刚刚公开的ARM Ethos-N ...

  2. OptimalSolution(1)--递归和动态规划(1)斐波那契系列问题的递归和动态规划

    一.斐波那契数列 斐波那契数列就是:当n=0时,F(n)=0:当n=1时,F(n)=1:当n>1时,F(n) = F(n-1)+F(n-2). 根据斐波那契数列的定义,斐波那契数列为(从n=1开 ...

  3. Redis5源码解析-Sentinel

    简单的概念就不解释.基于Redis5.0.5 从Sentinel主函数触发 在sentinel.c文件的最后面可以发现sentinelTimer函数,这个就是Sentinel的主函数,sentinel ...

  4. SpringCloud之Feign和Ribbon的选择(五)

    Ribbon Ribbon 是一个基于 HTTP 和 TCP 客户端的负载均衡器它可以在客户端配置 ribbonServerList(服务端列表),然后轮询请求以实现均衡负载它在联合 Eureka 使 ...

  5. PHP比较IP大小

    function cmpLoginIP($a, $b) { return bindec(decbin(ip2long($a['loginIp']))) > bindec(decbin(ip2lo ...

  6. Go-back-N Implementation of reliable data transport (RDT)

    [Author] @ Yubao Liu Tables 1.Overview 2.Design explanation 2.1Implemented Routines 2.2Called Routin ...

  7. 匹马行天下之思维决定高度篇——道道道,学习Java之道

    致Java星球的程序员兄弟们的一封信 亲爱的Java星球的程序员兄弟们: 你们好!我是来自地球的一名Java程序员,首先我代表地球人对贵星球的高司令来到地球传授Java语言,造福了全人类,造福了整个地 ...

  8. Wininet-Post

    #include "stdafx.h"#include <Windows.h>#include <wininet.h>#include <iostre ...

  9. 学习笔记48_Memcache跟用户登录模块结合

    public interface ICacheWriter {  void AddCache(string key,object value, DateTime expDate);  void Add ...

  10. 论文阅读 Prefetch-aware fingerprint cache management for data deduplication systems

    论文链接 https://link.springer.com/article/10.1007/s11704-017-7119-0 这篇论文试图解决的问题是在cache 环节之前,prefetch-ca ...