python进阶

python 上下文管理

2019-08-19  本文已影响0人  落羽归尘

简介

        上下文管理属于流程控制特性中一部分,在python中,上下文管理语法主要是使用with关键词。with语句会设置一个临时的上下文,对对象进行控制,并且清除上下文,这样做的好处是能够减少错误,使得代码整洁易读。我们详细分析下流程控制的else,和上下文管理。

else字句

        当然,else是我们经常用的关键词,相信大家大部分都是使用于if-else对。其实在python中,还有其他情况能使用else字句,当然都属于流程控制的范涛。如for/else、while/else 和 try/else。

for i in range(10):
    pass
else:
    print("---else----")
输出结果:
---else----

当for循环中有break时,else字句不会执行:

for i in range(10):
    if i == 7:
        break
else:
    print("---else----")
flag = 5
while flag:
    flag -= 1
else:
    print("---else----")
输出结果:
---else----

其实else在上述语句中不是很常用,但是也是有些情况使用会很方便的,例如:

for i in range(10):
    if i == 12:
        break
else:
    print("列表中没有12")

上述情况下,使用else之后,无需设置控制标志或者额外的if语句,如果不使用else。恐怕要像下面这种写法了:

flag = 0
for i in range(10):
    if i == 12:
        flag = 1
        break
if flag:
    pass
else:
    print("列表中没有12")

可见,有些时候在for循环使用else,也能省去很多麻烦的。

with语句

        上下文管理器对象存在的目的是管理with语句,with语句的目的是简化try/finally 模式。用于保证一段代码执行后进行某些操作,即使抛出异常也会执行收尾工作。
        上下文管理器主要包含两个特殊方法,__enter____exit__,with开始时,会调用上下文管理器对象的__enter__方法,with结束后,会调用__exit__方法。
        最常见的with语句是文件打开,确保最后文件能够关闭:

with open("test.txt") as f:
    pass

f绑定到打开的文件上面,是调用上下文管理器对象的__enter__方法的结果。无论这个流程语句以何种情况结束,最后都会调用__exit__方法。
如下,定义一个简单的上下文管理器对象:

class Test(object):
    def __enter__(self):
        print("enter")

    def __exit__(self, exc_type, exc_value, traceback):
        print("exit")
        print(exc_type, exc_value, traceback)

with Test():
    pass
输出结果:
enter
exit
None None None

若有异常:

class Test(object):
    def __enter__(self):
        print("enter")

    def __exit__(self, exc_type, exc_value, traceback):
        print("exit",exc_type, exc_value, traceback,"exit")

with Test():
    a
输出结果:
enter
exit <class 'NameError'> name 'a' is not defined <traceback object at 0x000001A421F68708> exit
Traceback (most recent call last):
  File "c:/Users/DELL/Desktop/ssj/search/descrip.py", line 12, in <module>
    a
NameError: name 'a' is not defined

调用方法__enter__时,除了self,不会传其他参数的。
调用__exit__方法时:
没有异常发生时,除了self,传的三个参数都是None;
有异常情况时,三个参数的意义:
exc_type:异常类
exc_value:异常消息
traceback:traceback对象。
上下文管理器标准库中也有很多用法:
比如django数据库中的事务:

 with transaction.atomic():
    pass

threading 多线程中的锁:

whit threading.Lock():
    pass

        其实关于上下文管理器,有一个专门的内置库contextlib
这个模块提供了一个很实用的工具@contextmanager,这个装饰器能把生成器函数变成上下文管理器,

from contextlib import contextmanager

@contextmanager
def test():
    print("enter")
    yield "aaaa"
    print("exit")

with test() as f:
    pass
print(f)
输出结果:
enter
exit
aaaa

在使用@contextmanager装饰的生成器中,yield语句把上下分成两个部分,yield以上,是在with执行时,也就是调用方法__enter__时,yield下面的代码在调用__exit__方法时执行。

上一篇 下一篇

猜你喜欢

热点阅读