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

分类: 计算机技术
推荐阅读:
Python input()函数 在Python中,input()是一个内置函数,该函数从输入中读取一行,将其转换成字符串(不包括换行符)并返回;
Python compile()函数 在 Python 中,compile() 是一个内置函数,用于将字符串或AST对象编译成字节码或代码对象。编译后的字节码或代码对象可以在多个 Python 解释器中执行,从而避免每次执行时重新编译代码。
Rust解析TOML,结构体序列化和反序列化 在Rust中,可以使用标准库中的toml模块来解析和生成TOML格式的数据;serde与toml模块集成,可以将TOML字符串解析为任意Rust结构体,或将rust结构体序列化为TOML格式的字符串。
Python webbrowser模块的详细用法 webbrowser是python下一个内置的模块,该模块提供了一个高级接口,使你可以调用计算机中的浏览器以打开基于WEB的文档,比如常见的html网页;
从Nginx日志中提取UserAgent、IP等信息 有时我们需要用到大量UserAgent信息,而Nginx日志文件中包含了海量真实的UserAgent,从Nginx文件中提取所有UserAgent信息就很有必要;
如何防止WiFi被蹭网 本文将从攻击者的角度详细讨论一下WiFi密码是如何被知晓的,以及如何防范WiFi被蹭,可以这么说,就算告诉你我家WiFi密码,你也蹭不了我的网;