Python 高手编程系列三百二十一:作为一个函数 — contextlib 模块

使用类似乎是实现 Python 语言提供的任何协议最灵活的方法,但对许多使用场景来说
可能样板太多。标准库中新增了 contextlib 模块,提供了与上下文管理器一起使用的辅
助函数。它最有用的部分是 contextmanager 装饰器。你可以在一个函数里面同时提供
__enter__和__exit__两部分,中间用 yield 语句分开(注意,这样函数就变成了生成
器)。用这个装饰器编写前面的例子,其代码如下:
from contextlib import contextmanager
@contextmanager
def context_illustration():
print(‘entering context’)
try:
yield
except Exception as e:
print(‘leaving context’)
print(‘with an error (%s)’ % e)

需要再次抛出异常

raise
else:
print(‘leaving context’)
print(‘with no error’)
如果出现任何异常,该函数都需要再次抛出这个异常,以便传递它。注意,context_
illustration 在需要时可以有一些参数,只要在调用时提供这些参数即可。这个小的辅
助函数简化了常规的基于类的上下文 API,正如生成器对基于类的迭代器 API 的作用一样。
这个模块还提供了其他 3 个辅助函数。
• closing(element):返回一个上下文管理器,在退出时会调用该元素的 close
方法。例如,它对处理流的类就很有用。
• supress(*exceptions):它会压制发生在 with 语句正文中的特定异常。
• redirect_stdout(new_target)和 redirect_stderr(new_target):它
会将代码块内任何代码的 sys.stdout 或 sys.stderr 输出重定向到类文件
(file-like)对象的另一个文件。
上下文提供者
上下文装饰器确保函数可以运行在正确的上下文中,或者在函数前后运行一些代码。换
句话说,它设定并复位一个特定的执行环境。举个例子,当一个数据项需要在多个线程之间
共享时,就要用一个锁来保护它避免多次访问。这个锁可以在装饰器中编写,代码如下:
from threading import RLock
lock = RLock()
def synchronized(function):
def _synchronized(*args, **kw):
lock.acquire()
try:
return function(*args, **kw)
finally:
lock.release()
return _synchronized
@synchronized
def thread_safe(): # 确保锁定资源
pass
上下文装饰器通常会被上下文管理器(with 语句)替代,后者将在本章后面介绍。
你可能还不知道的其他语法元素
Python 语法中有一些元素不太常见,也很少用到。这是因为它们能提供的好处很少,
或者它们的用法很难记住。因此,许多 Python 程序员(即使有多年的经验)完全不知道这
些语法元素的存在。其中最有名的例子如下:
• for … else 语句。
• 函数注解(function annotation)。
for…else…语句
在 for 循环之后使用 else 子句,可以在循环“自然”结束而不是被 break 语句终
止时执行一个代码块:

for number in range(1):
… break
… else:
… print(“no break”)

for number in range(1):
… pass
… else:
… print(“break”)

break
这一语句在某些情况下很有用,因为它有助于删除一些“哨兵(sentinel)”变量,如果
出现 break 时用户想要保存信息,可能会需要这些变量。这使得代码更加清晰,但可能会
使不熟悉这种语法的程序员感到困惑。有人说 else 子句的这种含义是违反直觉的,但这
里介绍一个简单的技巧,可以帮你记住它的用法:for 循环之后 else 子句的含义是“没
有 break”。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值