• python的with


    with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源。

    比如文件使用后自动关闭、线程中锁的自动获取和释放等。

    with open('test.txt', 'r') as f:
        for line in f:
            print(line)

    运行机制

    with VAR = EXPR:
        BLOCK

    等价于

    VAR = EXPR
    VAR.__enter__()
    try:
        BLOCK
    finally:
        VAR.__exit__()

    VAR对应一个上下文管理器(context manager)。

    上下文管理器

    实现了__enter__()和__exit__()两个方法的类就是一个上下文管理器。

    class MyContextManager:
        def __enter__(self):
            print('before block run')
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('after block run')

    使用上下文管理MyContextManager

    with MyContextManager():
        print('run block')

    输出如下:

    before block run
    run block
    after block run

    MyContextManager也可以接受参数

    class MyContextManager:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __enter__(self):
            print('before block run')
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('after block run')
    
        def show(self):
            print('my name is:', self.name)
            print('my age is:', self.age)

    再次使用上下文管理MyContextManager

    with MyContextManager('logan', 27) as myCM:
        myCM.show()

    输出如下:

    before block run
    my name is: logan
    my age is: 27
    after block run

    这里用到了一个as: with context_manager as target

    target对应context_manager的__enter__()方法的返回值,返回值可以是context_manager自身,也可以是其他对象。

    contextlib.contextmanager

     contextmanager可以对生成器函数进行装饰,返回结果是一个上下文管理器。

    import contextlib
    
    @contextlib.contextmanager
    def MyGenerator():
        print('before yield')
        yield
        print('after yield')
    
    with MyGenerator():
        print('run block')

    输出如下:

    before yield
    run block
    after yield

    这里yield nothing,下面给个yield something的例子

    import contextlib
    
    @contextlib.contextmanager
    def MyGenerator():
        print('before yield')
        yield 'context manager'
        print('after yield')
    
    with MyGenerator() as cm:
        print('run block')
        print(cm)

    输出如下:

    before yield
    run block
    context manager
    after yield

    两个注意点

    1. yield之前的语句类似于__enter__(),yield之后的语句类似于__exit__()方法。

    2. yield返回一个上下文管理器,如果使用as语句,会被赋值给as语句中的target。

    try...finally

    当在try范围内产生一个异常时,会立即跳转到finally语句块。当finally语句块执行完毕后,会继续向上一层引发异常。

    参考资料:

    浅谈 Python 的 with 语句

  • 相关阅读:
    xcode
    2020上班第一天
    动态网页爬取方法
    静态网页爬虫获取数据的简单方法Xpath
    帆软9.0升级10.0(摘自帆软官方文档)
    linux下安装redis
    linux 命令笔记
    shell 编写mongodb linux下安装脚本
    pl/sql基础之三
    plsql基础二之集合
  • 原文地址:https://www.cnblogs.com/gattaca/p/7309192.html
Copyright © 2020-2023  润新知