400-616-5551

您所在位置: 首页> 学习课程> python培训 | Python 高级语法之contextmanager

python培训 | Python 高级语法之contextmanager

发布百知教育 来源:学习课程 2019-10-09

之前我们详细的讲解了Python中如何创建一个上下文管理器,我们通过实现__enter__和__exit__方法来实现一个上下文管理器,然后通过with语句来调用上下文管理器。


可是这种方法有一个弊端,那就是需要编写者对源码比较了解,如果我们要改动的代码不是我们自己所编写的怎么办?有没有一种办法将他人的代码改造之后,也能够使用with语句来调用呢?


答案是肯定的,今天我们就来说一说Python的高级语法之contextmanager装饰器。


首先我们回顾一下上篇文章最后的内容。我们定义了一个方法create_a,它是一个上下文管理器,我们对create_a可以使用with语句


class A:

    def __enter__(self):

        print('执行__enter__')

        return self


    def __exit__(self, exc_type, exc_val, exc_tb):

        print('执行__exit__')

        return True


    @staticmethod

    def query():

        print('执行query方法')



def create_a():

    return A()



with create_a() as a:

    a.query()

    print('执行with语句')

执行结果如下所示:


执行__enter__

执行query方法

执行with语句

执行__exit__

如果我们不用__enter__和__exit__的方法,要怎样才能实现相同的效果呢?

有了contextmanager其实很简单,我们只需要将代码做如下改造即可


from contextlib import contextmanager



class A:

    @staticmethod

    def query():

        print('执行query方法')



@contextmanager

def create_a():

    print('执行__enter__方法')

    yield A()

    print('执行__exit__方法')



with create_a() as a:

    a.query()

    print('执行with语句')

输出结果和最开始使用__enter__ __exit__是一样的。


下面说下具体步骤:


我们需要从contextlib中导入contextmanager

将contextmanager装饰器打在create_a方法上

将我们需要执行的enter方法写在上方

将A的对象返回,这里需要注意的是,返回要用yield,不能用return

将我们需要执行的exit方法写在最下方

上方面的代码利用contextmanager在未更改源代码的情况下,将create_a变成了一个上下文管理器。能用使用with来调用create_a。


虽然我们实现了功能,但是这里有个缺陷,那就是没有处理在with语句中处理的异常,我们使用with语句的目的,就是为了能够在发生异常的时候依然能够执行__exit__方法。


我们先来看一下,在上面的代码中,如果with语句中发生了异常,代码会如何运行。


更改with中的调用,人为增加一个异常:


with create_a() as a:

    number = 1 / 0

    a.query()

    print('执行with语句')

代码运行结果:



可以看到,在执行到__enter__方法后,直接抛出了异常,没有执行__exit__,那么要如何处理这种情况呢?也很简单,我们只需要在create_a中增加异常处理机制即可。


@contextmanager

def create_a():

    try:

        print('执行__enter__方法')

        yield A()

    except Exception:

        print('捕捉到了异常')

    finally:

        print('执行__exit__方法')

再次执行代码,运行结果如下所示:


执行__enter__方法

捕捉到了异常

执行__exit__方法

这样,我们在使用with语句时,无论是否发生异常,都可以执行__exit__中的内容了。



python培训:http://www.baizhiedu.com/python2019


上一篇:Python培训班 | 从零开始,这是入门Python最快的方式!

下一篇:应届生去公司找个Java程序员的职位需要什么技能?

相关推荐

www.baizhiedu.com

有位老师想和您聊一聊

关闭

立即申请