当前位置 主页 > 服务器问题 > Linux/apache问题 >

    Python with语句和过程抽取思想

    栏目:Linux/apache问题 时间:2019-12-23 20:40

    python中的with语句使用于对资源进行访问的场合,保证不管处理过程中是否发生错误或者异常都会执行规定的__exit__(“清理”)操作,释放被访问的资源,比如有文件读写后自动关闭、线程中锁的自动获取和释放等。

    与python中with语句有关的概念有:上下文管理协议、上下文管理器、运行时上下文、上下文表达式、处理资源的代码段。

    with语句的应用场景

      编程中有很多操作都是配套使用的,这种配套的流程可以称为计算过程,Python语言为这种计算过程专门设计了一种结构:with语句。比如文件处理就是这类计算过程的典型代表。

    使用with语句前后对比

    没有使用with语句之前,我们是这样打开一个文件的:

    try:
     # 1. [进入]
     f = open('a.txt', 'r', encoding="utf-8")
     # 2. [执行]
     print(f.read())
    finally:
     if f:
      # 3. [退出]
      f.close()

    python操作文件的流程一般就是这三步:

    1.[进入]用只读方式打开文件

    如果文件不存在,open()函数就会抛出一个IOError的错误,并且给出错误码和详细的信息告诉你文件不存在

    2.[执行]读取文件内容

    如果文件打开成功,接下来,调用read()方法可以一次读取文件的全部内容,Python把内容读到内存,用一个str对象表示

    3.[退出]关闭打开的文件

    文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的

    思考为什么关闭文件操作一定要放在finallly语句里?

      由于文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用。所以,为了保证无论是否出错都能正确地关闭文件,我们可以使用try ... finally来实现。

    发现共性:

    我们发现其实这种过程化的语句有共性,比如说在进去一个片段必须做某种超赞,处理工作又需要执行一个结束操作。比如上面的这段代码:

    finally:
     if f:
      f.close()

    就可以做一个封装。

    使用with语句后,我们是这样打开一个文件的:

    with open("a.txt", "r", encoding="utf-8") as f:
     print(f.read())

    这个with语句和前面的try ... finally结构是一样的,但是代码更佳简洁,并且不必调用f.close()方法。

    with语句的执行原理

    从解释器的角度去理解with语句执行流程。

    with语句的基本形式是:

    with 表达式 as 变量:
     语句块

      这样的一段代码可以称为一个上下文(context),在执行with语句时,解释器会先求出表达式的值,这个值(对象)是一个上下文管理器,并且假设这个对象拥有如下类的构造方法:

    def __enter__():
      # 描述进入上下文的动作
      pass
    
     def __exit__():
      # 描述退出上下文的动作
      pass

    with语句在求出这个上下文管理器对象之后,自动执行进入方法,并将这个对象的返回值赋值于 as 之后的变量,然后执行语句块。然后在退出上下文前,自动执行对象的退出方法

    python系统和标准库的一些类型定义了这对操作,可以直接用于with语句。比如文件对象就直接支持这一对操作,因此可以用在with语句的头部。

    如果你也有类似的计算过程需要抽取出来,那么可以自定义一个类,并且包含进入、退出方法。

    自定义open函数

    自己实现才发现,使用装饰器和生成器就能很好的解决这个问题,不需要用到类构造方法来实现;