深入理解with用法,不只是优雅

最常见的with用法

     操作文件的时候,我们经常写下如下的代码,但是你知道with的原理是什么吗?为神马要这么写吗?

with open("test.txt",mode='w') as my_file: 
    print("hello world")

先聊聊open()内置函数

    open()内置函数会返回一个文件对象,当我们对文件对象的方法进行调用,则是对文件内容的读写,接下来我们先看一个不使用with语句操作文件的例子

不使用with操作文件?

file = open('test.txt', 'w') 
file.write('hello world !') 
file.close()

此时可能出现2个坑

1、你很可能会忘记调用文件对象的close()方法,导致文件句柄一直被当前进程占用着,占用的内存会延迟释放(备注:当进程结束,也会释放)

2、调用文件对象的write()方法时直接出现异常,比如磁盘满了,此时程序会因为异常没有处理被结束,后续的close()方法也不会得到执行

如何避免上面的2个坑?

file = open('test.txt', 'w')

try: 
    
    file.write('hello world')

except Exception:

    print("啥也不干")

finally: 
    
    file.close()

使用try代码进行处理

1、当出现任何异常,except语句会执行

2、无论如何,finally代码块也会执行,不用担心close()不被调用

此时就有一个缺点:不够优雅,代码冗余太多

with语句,自然而然的优雅起来

with open('test.txt', 'w') as file: 
    file.write('hello world')

发生异常会自动被处理

文件对象会自动被关闭

你肯定想问了,with是如何做到这些的呢?这将引出一个重要的概念:上下文管理器

重要概念:上下文管理器对象

    with 语句的实现原理建立在上下文管理器对象(简称上下文管理器)之上

python中有明确定义:同时实现 __enter__ 和 __exit__ 方法的对象称为上下文管理器对象

class Baby(object): 
    def __enter__(self): 
        print('===baby===') 
        return self 

    def __exit__(self, exc_type, exc_val, exc_tb): 
        print('===close baby===') 
        return True 

    def operate(self): 
        temp = 1/0 
        return temp

同时约束__enter__方法与__exit__方法的用法

__enter__:必须返回一个对象

__exit__:必须返回boolean值,表示异常是否被处理,True表示已经处理,False表示继续抛出

__exit__的3个参数

exc_type:异常类型

exc_val:异常值

exc_tb:异常的错误栈信息

当没有异常时,自动回调时传入的都是None,存在异常时,就是说明说的3个对象

你可以执行这段代码试试,我说的对不对

with Baby() as my_baby: 
    baby.operate() 

print("Over")

File对象是这么做的(非完整源码)

class File: 
    def __init__(self, file_path, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True): 
        self._file = open(file_path, mode=mode, buffering=buffering, encoding=encoding, 
        errors=errors, newline=newline, closefd=closefd) 

    def __enter__(self): 
        return self 
    
    def __exit__(self, exc_type, exc_val, exc_tb): 
        self._file.close() 

     #省略很多源码……

再回头with语句的工作过程

with open('test.txt', 'w') as my_file: 
    my_file.write('hello world!')

1、open()内置函数会最先执行,它会返回一个File对象(with语句后面跟着的是上下文管理器对象即可)

2、File对象的__enter__()方法被自动调用

3、__enter__()方法的返回值赋值到as后面的变量,由于File对象的__enter__()方法返回的时self

4、上下文管理器中的代码块开始执行,即my_file.write()这行代码开始执行

5、File对象的__exit__()方法被自动调用,其中__exit__中的有close()方法的调用,文件关闭

with语句两个用途

1、释放必要资源

2、处理异常

总结

1、熟悉with语句,操作文件游刃有余

2、自己写用于with语句的对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值