使用Python实现with结构的@contextmanager方法详解

 更新时间:2023年07月21日 09:36:50   作者:孔天逸  
这篇文章主要介绍了使用Python实现with结构的@contextmanager方法详解,这个结构的好处,一个是简洁,一个是当我们对文件操作的逻辑很长的时候,不会因为忘了关闭文件而造成不必要的错误,需要的朋友可以参考下

常见with结构

常见的with结构是在进行文件操作时,比如

# 中规中矩的写法
f = open("test.txt", "w")
f.write("hello world!")
f.close()
# 采用with结构
with open("test.txt", "w") as f:
  f.write("hello world!")

这个结构的好处,一个是简洁,一个是当我们对文件操作的逻辑很长的时候,不会因为忘了关闭文件而造成不必要的错误。

类似的,当我们在某些时候不希望遗忘一些重要的语句的时候,可以自己封装个with结构,比如关闭数据库链接等情况。

一般实现方法

with结构一般的实现方法是在定义类的时候重载__enter__方法和__exit__方法

比如我们可以通过如下代码来模拟一下上面两段代码前者到后者的转化

# -*- coding: utf-8 -*-
class myOpen():
    def __init__(self, name, state):
        self.f = open(name, state)
    # 返回值是with...as...中as出来的东西,如下面的f
    def __enter__(self):
        return self.f
    # 在with...as...语句块自动执行完之后执行
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.f.close()
if __name__ == "__main__":
    with myOpen("test.txt", "w") as f:
        f.write("hello world!")

@contextmanager方法

好像上面这种方法实现起来with结构有那么一点点麻烦,那么就进入主题吧,有一种逼格又高,又简便的方法,先上代码,仍以打开文件为例:

# -*- coding: utf-8 -*-
from contextlib import contextmanager
@contextmanager
def myOpen(name, state):
  try:
    f = open(name, state)
    yield f
  finally:
      f.close()
if __name__ == "__main__":
  with myOpen("test.txt", "w") as f:
      f.write("hello world!")

可以看出这里只要定义一个函数,然后在它的头部加上@contextmanager就好了

这个函数应该怎么定义呢?我们去源码里看一下就好,里面给出了详细的注释

def contextmanager(func):
    """@contextmanager decorator.
    Typical usage:
        @contextmanager
        def some_generator(<arguments>):
            <setup>
            try:
                yield <value>
            finally:
                <cleanup>
    This makes this:
        with some_generator(<arguments>) as <variable>:
            <body>
    equivalent to this:
        <setup>
        try:
            <variable> = <value>
            <body>
        finally:
            <cleanup>
    """
    @wraps(func)
    def helper(*args, **kwds):
        return GeneratorContextManager(func(*args, **kwds))
    return helper

通过注释我们可以看到,我们可以通过给一个try…finally…结构的函数头部加上@contextmanager就可以通过with…as…结构来调用它了

这样try块中yield的数据被as出来,finally块中的数据在with..as..块结束的时候被执行。

到此这篇关于使用Python实现with结构的@contextmanager方法详解的文章就介绍到这了,更多相关Python实现with结构内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python 在区块链智能合约开发中的应用与实践小结

    Python 在区块链智能合约开发中的应用与实践小结

    Python作为一种广泛应用的编程语言,在区块链智能合约开发中扮演着重要角色,通过使用Python框架如Brownie和Web3.py,开发者可以轻松编写和部署智能合约,感兴趣的朋友一起看看吧
    2024-09-09
  • django和flask哪个值得研究学习

    django和flask哪个值得研究学习

    在本篇文章里小编给大家整理的是一篇关于django和flask哪个值得研究学习内容,需要的朋友们可以参考下。
    2020-07-07
  • 解读keras中的正则化(regularization)问题

    解读keras中的正则化(regularization)问题

    这篇文章主要介绍了解读keras中的正则化(regularization)问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • python实现rar解压和压缩的方法(附源码)

    python实现rar解压和压缩的方法(附源码)

    数据量现在越来越大,压缩文件在日常生活中很常用,这篇文章主要给大家介绍了关于python实现rar解压和压缩的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-10-10
  • Python2.7下安装Scrapy框架步骤教程

    Python2.7下安装Scrapy框架步骤教程

    本篇文章主要介绍了Python2.7下安装Scrapy框架步骤教程,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • Pycharm cannot set up a python SDK问题的原因及解决方法

    Pycharm cannot set up a python SDK问题的原因及解决方法

    这篇文章主要给大家介绍了关于Pycharm cannot set up a python SDK问题的原因及解决方法,这个问题已经不是第一次出现了,所以干脆总结下,需要的朋友可以参考下
    2022-06-06
  • Python全栈之字符串和列表相关操作

    Python全栈之字符串和列表相关操作

    这篇文章主要为大家介绍了Python字符串和列表相关操作,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-12-12
  • Python基础之字典的详细使用教程

    Python基础之字典的详细使用教程

    字典作为Python的一个内置数据结构,和列表一样都是可变序列的,但是它是无序的,以键值对的方式存储数据。本文将详解一下Python中字典的使用,需要的可以参考一下
    2022-07-07
  • 在django模板中实现超链接配置

    在django模板中实现超链接配置

    今天小编就为大家分享一篇在django模板中实现超链接配置,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-08-08
  • tensor和numpy的互相转换的实现示例

    tensor和numpy的互相转换的实现示例

    这篇文章主要介绍了tensor和numpy的互相转换的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08

最新评论