Python内置方法详解(8)

  定义使用 with 声明创建的语句块最开始上下文管理器应该做些什么。注意 __enter__ 的返回值会赋给 with 声明的目标,也就是 as 之后的东西。

  __exit__(self, exception_type, exception_value, traceback)

  定义当 with 声明语句块执行完毕(或终止)时上下文管理器的行为。它可以用来处理异常,进行清理,或者做其他应该在语句块结束之后立刻执行的工作。如果语句块顺利执行, exception_type , exception_value 和 traceback 会是 None 。否则,你可以选择处理这个异常或者让用户来处理。如果你想处理异常,确保 __exit__ 在完成工作之后返回 True 。如果你不想处理异常,那就让它发生吧。

  对一些具有良好定义的且通用的设置和清理行为的类,__enter__ 和 __exit__ 会显得特别有用。你也可以使用这几个方法来创建通用的上下文管理器,用来包装其他对象。下面是一个例子:

class Closer: '''一个上下文管理器,可以在with语句中 使用close()自动关闭对象''' def __init__(self, obj): self.obj = obj def __enter__(self, obj): return self.obj # 绑定到目标 def __exit__(self, exception_type, exception_value, traceback): try: self.obj.close() except AttributeError: # obj不是可关闭的 print 'Not closable.' return True # 成功地处理了异常

  这是一个 Closer 在实际使用中的例子,使用一个FTP连接来演示(一个可关闭的socket):

>>> from magicmethods import Closer >>> from ftplib import FTP >>> with Closer(FTP('ftp.somesite.com')) as conn: ... conn.dir() ... # 为了简单,省略了某些输出 >>> conn.dir() # 很长的 AttributeError 信息,不能使用一个已关闭的连接 >>> with Closer(int(5)) as i: ... i += 1 ... Not closable. >>> i 6

  看到我们的包装器是如何同时优雅地处理正确和不正确的调用了吗?这就是上下文管理器和魔法方法的力量。Python标准库包含一个 contextlib 模块,里面有一个上下文管理器 contextlib.closing() 基本上和我们的包装器完成的是同样的事情(但是没有包含任何当对象没有close()方法时的处理)。

  11. 创建描述符对象

  描述符是一个类,当使用取值,赋值和删除 时它可以改变其他对象。描述符不是用来单独使用的,它们需要被一个拥有者类所包含。描述符可以用来创建面向对象数据库,以及创建某些属性之间互相依赖的类。描述符在表现具有不同单位的属性,或者需要计算的属性时显得特别有用(例如表现一个坐标系中的点的类,其中的距离原点的距离这种属性)。

  要想成为一个描述符,一个类必须具有实现 __get__ , __set__ 和 __delete__ 三个方法中至少一个。

  让我们一起来看一看这些魔法方法:

  __get__(self, instance, owner)

  定义当试图取出描述符的值时的行为。 instance 是拥有者类的实例, owner 是拥有者类本身。

  __set__(self, instance, owner)

  定义当描述符的值改变时的行为。 instance 是拥有者类的实例, value 是要赋给描述符的值。

  __delete__(self, instance, owner)

  定义当描述符的值被删除时的行为。instance 是拥有者类的实例

  现在,来看一个描述符的有效应用:单位转换:

class Meter(object): '''米的描述符。''' def __init__(self, value=0.0): self.value = float(value) def __get__(self, instance, owner): return self.value def __set__(self, instance, owner): self.value = float(value) class Foot(object): '''英尺的描述符。''' def __get(self, instance, owner): return instance.meter * 3.2808 def __set(self, instance, value): instance.meter = float(value) / 3.2808 class Distance(object): '''用于描述距离的类,包含英尺和米两个描述符。''' meter = Meter() foot = Foot()

  12. 拷贝

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/b955b7ea058f3baffa168301f7ce90bd.html