一、需求的提出:
1、任务系统(任务机制) 2、对统计和日志友好
二、原理:
当对象的某一属性的值发生改变时,在不影响对该对象属性的正常运算(赋值)操作的情况下,是该对象属性触发属性值改变的事件信号,并通过已注册的监听机制来响应相应的对象属性改变事件。
三、准备知识:
1、类的说明书—--------元类:
classMetaC(type):
def__init__(cls, name, base, dct):
printname, base, dct
super(MetaC,cls).__init__(name, base, dct)
defsay(cls):
print“I am class ”,cls.__name__
classA(object):
__metaclass__= MetaC
A.say() # “I am class A”
输出结果: <class'__main__.A'> A (<type 'object'>,) {'__module__': '__main__', '__metaclass__': <class'__main__.MetaC'>}
2、类的描述器:
当一个对象拥有__get__(必要),和__set__ __delete__(可选)方法时,该对象可以成为一个描述器。
当一个描述器作为一个类的属性时,则该类的此属性的取得、赋值和删除操作将由该描述器所对应的 __get__ __set__ 和 __delete__ 方法来决定如何处理。
3、实现:
将数据库表字段一一作为Model对象的属性描述器,通过元类构造反射过程,自省出表结构,通过实现表对应字段的描述器的 __set__ 和__delete__方法,来实现表字段属性的值发生改变时的事件出发机制。
四、伪代码实例:
classAttrProxy(object):
def__init__(self, **kwargs):
self.attr_name= kwargs.get(“attr_name”)
self.is_main_key= kwargs.get(“is_main_key”, False)
self.default_value= kwargs.get('default_value')
def__set__(self, obj, value):
setattr(obj,'_'+self.attr_name, value)
#属性改变事件的出发机制............
def__get__(self, obj):
getattr(obj,'_'+self.attr_name, self.default_value)
classStringProperty(AttrProxy):
def__init__(self, **kwargs):
super(StringProperty,self).__init__(**kwargs)
classBlobProperty(AttrProxy):
def__init__(self, **kwargs):
super(StringProperty,self).__init__(**kwargs)
classModelMeta(type):
#通过自省来整理表的结构
def__init__(cls, name, base, dct):
cls.attrs= [] #相当于seq_attrs列表
cls.pickle_attrs= [] #相当于 adv_seq_attrs列表
forattr_name, attr_obj in dct.items():
ifisinstance(attr_obj, AttrProxy):
ifnot attr_obj.attr_name:
attr_obj.attr_name= attr_name
ifattr_obj.is_main_key:
cls.main_key= attr_obj.attr_name #设定主键
cls.attrs.append(attr_obj.attr_name)
ifisinstance(attr_obj, BlobProperty):
cls.pickle_attrs.append(attr_obj.attr_name)
classModel(object):
__metaclass__= ModelMeta
classUser(Model):
#与表字段对应的描述器
uid= StringProperty(is_main_key = True)
name= StringProperty()
friends= BlobProperty(default_value = [])
def__init__(self, uid = None):
self.uid= uid
super(User,self).__init__()
rk_user= User('123')
rk_user.name= “user name”
联系客服