Python|Python 技巧探究(上下文管理器和with语句)
文章图片
一:前言
Python 里面的 with 语句是被认为是晦涩难懂的特征之一,但是当你窥视它的内部你就会发现这里面并没有什么魔法。事实上它可以帮助我们写一些整洁和可读性高的代码。
那么 with 语句适合用于哪方面呢?它可以帮助我们简化一些常见的资源管理模式,允许它们被提取和重用。
二:案例探究
还是来看一个最常见的打开文件的例子吧!
with open('name.txt','w') as f:
f.write('hello world')
使用 with 语句去打开文件的好处在于,不管文件是否正常打开,最后文件都会被正常的关闭。实际上前面的代码可以翻译为下面的方式:
f = open('name.txt','w')
try:
f.write('hello world')
finally:
f.clouse()
当然这样写看起来确实挺废话的,但是其实 try...finally 语法是很重要的。
如果不用这个语法,可能会这样写:
f = open('name.txt','w')
f.write('hello world')
f.clouse()
这样的写法看起来挺正常的,但是实际上它保证不了文件的正常关闭,如果文件没有正常关闭就会出现很多问题,所以使用 with 语句是很有必要的,它帮助我们正确的获取和释放资源。
with 语句的另一个好用的例子是在 Python 的标准库里的 threading.Lock
lock = threading.Lock# 普通的方式:
lock.acquir()
try:
# do something
finally:
lock.release()# 更好的方式:
with lock:
# do something
通过这两个例子可以看到:使用 with 语句允许我们抽象更多的资源处理逻辑,取代每次显式的使用 try...finally 语句,方便我们写代码。舒服了哦!
with 语句可以使得处理系统资源的代码可读性更高,它帮助我们避免 bug 或者忘记释放资源。
三:让自己的项目支持with语句 现在其实觉得 open() 和 threading.Lock 没啥特殊或者魔法的。他们实际上都是可以使用 with 语句的。 我们也可以在类里面通过实现上下门管理器提供一些功能。
啥是上下文管理器( context manager) ?它是一个简单的接口,最基本的是我们写的这个类要实现 双下划线方法:
__enter__
和 __exit__
,Python 会在资源管理中适当的调用这两个方法。让我们看看它是怎么实现 open() 上下文管理的:
class ManagedFile:
def __init__(self, name)
self.name = namedef __enter__(self):
self.file = open(self.name, 'w')
return self.filedef __exit__(self, exc_type, exc_val, exc_tb):
if self.file:
self.file.close()
这个
ManagedFile
类就实现了上下文管理器协议,那么就支持使用 with 语句,就像使用最开始的 open() 的例子那样:with ManagedFile('name.txt') as f:
f.write('hello Python')
当使用 with 语句进入上下文管理器时 Python 调用
__enter__
方法,同时将获取到资源,当离开上下文管理器的时候 Python 调用 __exit__
方法去释放资源。像上面这样写一个基于上下文管理器的累不是在Python中支持 with 语句的唯一方法。 Python 标准库中的
contextlib
模块提供了一些基于上下文管理器的协议。【Python|Python 技巧探究(上下文管理器和with语句)】例如我们可以使用
contextlib.contextmanager
装饰一个基于生成器的工厂函数,这样就可以使用 with 语句,来看看例子吧:from contextlib import contextmanager@contextmanager
def manager_file(name):
try:
f = open(self.name, 'w')
yield f
finally:
f.close()
这样使用:
with manager_file('name.txt') as f:
f.write('hello python')
在这个例子中
manager_file()
是一个生成器,在开始的时候获取到资源,然后暂时性的停止程序 yiled
这个资源给调用者。当调用者离开了上下文,这个生成器就会继续执行后续的代码,所以最后资源可以被释放给系统。上面一个基于类的和基于生成器的方法去使用 with 语句是等价的,选一个可读性好的就行。
这里有一个问题就是,基于装饰器的实现方法要求开发者懂一些例如装饰器、生成器这样高级的 Python 语法概念。不过真的想学习 Python 这些高级语法也是要学习的。
推荐阅读
- 韩语学习的这几个技巧你掌握了就不怕学不会啦!
- python|python 玩转微信系列1 用饼图展示好友性别比例
- Python总结-----爬虫
- python小白爬虫第一篇
- Python基础|使用Python求解数独
- 数据结构与算法|堆排序python实现及时间复杂度分析
- pandans小技巧
- 95后员工沟通技巧
- 薇娅直播带货技巧
- 4.|4. Python 正则表达式