wordpress google linux Windows 开源 apache 微软 mysql shell Android java Ubuntu nginx 程序员 Python php HTML5 Firefox centos linux命令

Python的神奇方法指南:上下文管理

在 Python2.5 里引入了一个新关键字(with)使得一个新方法得到了代码复用。 上下文管理这个概念在 Python 中早已不是新鲜事了(之前它作为库的一部分被实现过),但直到 PEP343 才作为第一个类语言结构取得了重要地位而被接受。 你有可能早就已经见识过 with 声明:

with open('foo.txt') as bar:
    # 对bar执行某些动作

上下文管理允许对对象进行设置和清理动作,用 with 声明进行已经封装的操作。 上下文操作的行为取决于 2 个神奇方法:

__enter__(self)

定义块用 with 声明创建出来时上下文管理应该在块开始做什么。 注意,__enter__ 的返回值必须绑定 with 声明的目标,或是 as 后面的名称。

__exit__(self,  exception_type, exception_value, traceback)

定义在块执行(或终止)之后上下文管理应该做什么。 它可以用来处理异常,进行清理,或行动处于块之后某些总是被立即处理的事。 如果块执行成功的话,excepteion_type,exception_value,和 traceback 将会置None。 否则,你可以选择去处理异常,或者让用户自己去处理。 如果你想处理,确保在全部都完成之后__exit__ 会返回 True。 如果你不想让上下文管理处理异常,那就让它发生好了。

__enter__ 和 __exit__ 对那些已有良好定义和对设置,清理行为有共同行为的特殊类是有用。 你也可以使用这些方法去创建封装其他对象通用的上下文管理。 看下面的例子:

class Closer:
    '''用with声明一个上下文管理用一个close方法自动关闭一个对象'''

    def __init__(self, obj):
        self.obj = obj

    def __enter__(self):
        return self.obj # 绑定目标

    def __exit__(self, exception_type, exception_val, trace):
        try:
            self.obj.close()
        except AttributeError: #obj不具备close
            print 'Not closable.'
            return True # 成功处理异常

以下是一个对于 Closer 实际应用的一个例子,使用一个 ftp 连接进行的演示(一个可关闭的套接字):

>>> from magicmethods import Closer
>>> from ftplib import :;;
>>> with Closer(FTP('ftp.somsite.com')) as conn:
...     conn.dir()
...
# 省略的输出
>>> conn.dir()
# 一个很长的AttributeError消息, 不能关闭使用的一个连接
>>> with Closer(int(5)) as i:
...     i += 1
...
Not closeable.
>>> i
6

瞧见我们如何漂亮地封装处理正确或不正确的用例了吗?那就是上下文管理和神奇方法的威力。

延伸阅读

评论