Python里with语句的用法与技巧

本文将详细讲解Python语言中with语句的用法,以及如何让自定义的类也支持with语句;

先看一段Python读取文件的代码:

class TooBig(Exception):pass

fp = open("text.txt",'r')
data = fp.read()
fp.close()
if len(data) > 10:
    raise TooBig
    
print(data)

这段代码如果使用with关键字,能大大提升阅读性:

class TooBig(Exception):pass

with open("text.txt",'r') as fp:
    data = fp.read()
    if len(data) > 10:
        raise TooBig

print(data)

with是如何实现的

with语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的清理操作,释放资源,比如文件使用后自动关闭、线程锁中的自动获取和释放等;

python中有两个特殊的方法构成上下文管理协议,分别是__enter____exit__;要让自定义的类支持with语句,需要定义并实现它们;

class test:
    def __init__(self, name):
        self.name = name
        print("__init__")

    def say(self):
        print("hello,",self.name)

    def __enter__(self):
        print("__enter__")
        return self   #可以返回不同的对象

    def __exit__(self, exc_type, exc_value, exc_tb):
        
        print("__exit__")
        if exc_tb:
            print("exited with exception raised.")
        else:
            print("exited without exception.")

with test("iKun") as k:
    k.say()
    #raise Exception

程序运行结果:

__init__
__enter__
hello, iKun
__exit__
exited without exception.

test类中的__enter__()方法返回的是自身的引用,这个引用可以赋值给as子句中的k变量(也可省略);返回值的类型可以根据实际需要设置为不同的类型,不必是上下文管理器对象本身。

线程锁的应用

with语句也尝尝用于线程锁的使用上:

import threading
lock= threading.Lock()

#lock.acquire()
#pass
#lock.release()

with lock:
    pass

其他参考

更多上下文管理器的高级用法,请参考contextlib模块中的contextmanage装饰器、nested函数和closing上下文管理器;

这些对象,可以对已有的生成器函数或对象进行包装,加入对上下文管理器协议的支持,避免了专门编写上下文管理器来支持with语句。

原创内容,如需转载,请注明出处;

本文地址: https://www.perfcode.com/p/502.html

分类: 计算机技术
推荐阅读:
在Windows系统下启动和终止MySQL服务 Windows平台下要启动MySQL服务只需以管理员权限运行命令net start mysql80,要关闭服务运行net stop mysql80;
MySQL AES_ENCRYPT()、AES_DECRYPT()函数 AES_ENCRYPT()和AES_DECRYPT()使用官方AES算法实现数据的加密和解密;其密钥默认长度为128位,默认块加密模式为ECB;
Python filter()函数 在Python中,filter()是一个内置函数,它有两个参数:一个函数和一个可迭代对象(比如列表、元组或集合)。它会对可迭代对象中的每个元素调用给定的函数,并返回一个新的可迭代对象,其中只包含符合条件的元素。
function main is undeclared in the main package解决办法 这是一个Golang新手可能会碰到的低级错误,它表明你的main包中不包含main()函数;
C程序计算二阶行列式的值 本文将使用C语言编写程序计算二阶行列式的值;程序通过定义一个2*2数组用于存储输入的二阶行列式;再通过前文的公式计算出二阶行列式的值;
Rust入门示例教程 该教程是一个可运行示例的集合,这些示例说明了各种Rust概念和标准库;如果你不喜欢阅读大量的文档来学习编程语言,那么该示例教程就很适合你,它不仅覆盖了你要学习的知识,而且有很多的篇幅来解释代码;