zoukankan      html  css  js  c++  java
  • 面对对象高级之魔法方法

    一、__enter__ 和 __exit__

    python中实现了__enter__和__exit__方法支持上下文管理器协议。上下文管理器就是支持上下文管理器协议的对象,它是为了with而生。当with语句在开始运行时,会在上下文管理器对象上调用 __enter__ 方法。with语句运行结束后,会在上下文管理器对象上调用 __exit__ 方法

    1.with语句是什么?

    有一些任务,可能事先需要设置,事后做清理工作。对于这种场景,Python的with语句提供了一种非常方便的处理方式。一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。

    如果不用with语句,代码如下:

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

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

    [进入]用只读方式打开文件
    如果文件不存在,open()函数就会抛出一个IOError的错误,并且给出错误码和详细的信息告诉你文件不存在
    
    [执行]读取文件内容
    如果文件打开成功,接下来,调用read()方法可以一次读取文件的全部内容,Python把内容读到内存,用一个str对象表示
    
    [退出]关闭打开的文件
    文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的
    

    思考为什么关闭文件操作一定要放在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()方法。

    2.with语句的执行原理

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

    with语句的基本形式是:

    with 表达式 as 变量:
        语句块
    

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

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

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

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

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

    用途或者说好处:

    1.使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
    
    2.在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处
    

    3.实现自定义with 类

    class MyClass:
        def __init__(self,file_name,mode='r',encoding='utf-8'):
            self.fine_name = file_name
            self.mode = mode
            self.encoding = encoding
    
    
        def __enter__(self):
            print("进入上下文")
            self.file = open(self.fine_name,mode=self.mode,encoding=self.encoding)
            return self.file
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("退出上下文")
            self.file.close()
    
    
    with MyClass('test.txt','w',encoding='utf-8') as f:
        f.write("test msg")
    print('hello world')
    

      

  • 相关阅读:
    pip安装报错 解决办法
    django admin 支持时间更改
    fiddler抓包工具
    session token两种登陆方式
    面向对象内置方法
    linux 命令
    flask
    celery
    mac添加redis 环境变量
    Django请求流程图
  • 原文地址:https://www.cnblogs.com/panwenbin-logs/p/13556261.html
Copyright © 2011-2022 走看看