首页 > 编程 > Python > 正文

Python类装饰器实现方法详解

2020-02-16 00:15:45
字体:
来源:转载
供稿:网友

本文实例讲述了Python类装饰器。分享给大家供大家参考,具体如下:

编写类装饰器

类装饰器类似于函数装饰器的概念,但它应用于类,它们可以用于管理类自身,或者用来拦截实例创建调用以管理实例。

单体类

由于类装饰器可以拦截实例创建调用,所以它们可以用来管理一个类的所有实例,或者扩展这些实例的接口。

下面的类装饰器实现了传统的单体编码模式,即最多只有一个类的一个实例存在。

instances = {} # 全局变量,管理实例def getInstance(aClass, *args):  if aClass not in instances:    instances[aClass] = aClass(*args)  return instances[aClass]   #每一个类只能存在一个实例def singleton(aClass):  def onCall(*args):    return getInstance(aClass,*args)  return onCall为了使用它,装饰用来强化单体模型的类:@singleton    # Person = singleton(Person)class Person:  def __init__(self,name,hours,rate):    self.name = name    self.hours = hours    self.rate = rate  def pay(self):    return self.hours * self.rate@singleton    # Spam = singleton(Spam)class Spam:  def __init__(self,val):    self.attr = valbob = Person('Bob',40,10)print(bob.name,bob.pay())sue = Person('Sue',50,20)print(sue.name,sue.pay())X = Spam(42)Y = Spam(99)print(X.attr,Y.attr)

现在,当Person或Spam类稍后用来创建一个实例的时候,装饰器提供的包装逻辑层把实例构建调用指向了onCall,它反过来调用getInstance,以针对每个类管理并分享一个单个实例,而不管进行了多少次构建调用。

程序输出如下:

Bob 400
Bob 400
42 42

在这里,我们使用全局的字典instances来保存实例,还有一个更好的解决方案就是使用Python3中的nonlocal关键字,它可以为每个类提供一个封闭的作用域,如下:

def singleton(aClass): instance = None def onCall(*args): nonlocal instance if instance == None:  instance = aClass(*args) return instance return onCall

当然,我们也可以用类来编写这个装饰器——如下代码对每个类使用一个实例,而不是使用一个封闭作用域或全局表:

class singleton: def __init__(self,aClass): self.aClass = aClass self.instance = None def __call__(self,*args): if self.instance == None:  self.instance = self.aClass(*args) return self.instance

跟踪对象接口

类装饰器的另一个常用场景是每个产生实例的接口。类装饰器基本上可以在实例上安装一个包装器逻辑层,来以某种方式管理其对接口的访问。

前面,我们知道可以用__getattr__运算符重载方法作为包装嵌入到实例的整个对象接口的方法,以便实现委托编码模式。__getattr__用于拦截未定义的属性名的访问。如下例子所示:

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表