VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > 简明python教程 >
  • PythonI/O进阶学习笔记_7.python动态属性,__new__和__init__和元类编程(下)(4)

可以看见args的列传进去的基本就是name(类名)、bases、attrs(属性dict)。将参数用这三个变量代替。与django中设置的变量一致。
对传递进去的attrs进行操作,如果是在User内定义的charfield、interfield这种类型的字段,直接用__new__生成对应的key、value。
但是对User类中定义的meta这类属性,对里面的一些属性的定义就需要做对应的处理。
又因为我们想把InterField、CharField这种属性描述符作为key,value存储,meta属性里的一些字段做特定处理,所以我们让各种属性描述符类继承同一个Field来判断是否都是Field类来做统一key value处理。
在User继承了改动过的元类之后。再User类中定义init,就能再pycharm中看到User中的变量。
复制代码
class Field:
    pass
class ModelMetaClass(type):
    def __new__(cls, name, bases, attrs, **kwargs):
        fields=dict()
        for key,value in attrs.items():
            if isinstance(value,Field):
                fields[key]=value
        attrs_meta=attrs.get("Meta",None)
        _meta={}
        db_table=name.lower()
        if attrs_meta is not None:
            table=getattr(attrs_meta,"db_table",None)
            if table is not None:
                db_table=table
        attrs["db_table"]=db_table
        attrs["_meta"]=attrs_meta
        attrs["fields"]=fields
        del fields["Meta"]
        return super().__new__(cls,name, bases, attrs,**kwargs)
复制代码

debug之后的效果:

 

c.定义User类的父类

但是在我们实际应用的时候,不可能每个User去定义__init__函数,save函数这样,所以我们就用一个modle父类,让User这些类来继承。
需要注意的是:
如果定义一个父类BaseModel,需要在BaseModel继承的元类中判断如果传进来的name是BaseModel,就直接__new__就可以了。因为在BaseModel中,是没有定义fields这些东西的。
并且在父类中,定义好save方法。
最后完整的代码为:
复制代码
import numbers
class Field:
    pass
class InterField(Field):
    def __init__(self,db_column=None,min_value=None,max_value=None):
        self._min_value=min_value
        self._max_value=max_value
        self.db_column=db_column
        if self._min_value is not None:
            if not isinstance(self._min_value,numbers.Integral):
                raise ValueError("Value Must be Intergral")
            elif self._min_value < 0:
                raise ValueError("Value Must large than 0")


        if self._max_value is not None:
            if not isinstance(self._max_value,numbers.Integral):
                raise ValueError("Value must be Intergral")
            elif self._max_value <0 :
                raise  ValueError("Value must large than 0")
        if max_value < min_value:
            raise ValueError("Max must large than min ")

    def __get__(self, instance, owner):
        return self._value

    def __set__(self, instance, value):
        if not isinstance(value,numbers.Integral):
            raise ValueError("Not intergral")
        self._value=value

class CharField(Field):
    def __init__(self,db_column=None,max_length=None):
        self.db_column=db_column
        self._max_length=max_length
        if not max_length:
            raise ValueError("You must special the charfield length")

    def __get__(self, instance, owner):
        return self._value


    def __set__(self, instance, value):
        self._value=value
        if len(value) > self._max_length:
            raise ValueError("Value's length must less than max length")

class ModelMetaClass(type):
    def __new__(cls, name, bases, attrs, **kwargs):
        if name=="BaseModel":
            super().__new__(cls,name,bases,attrs,**kwargs)

        fields=dict()
        for key,value in attrs.items():
            if isinstance(value,Field):
                fields[key]=value
        attrs_meta=attrs.get("Meta",None)
        _meta={}
        db_table=name.lower()
        if attrs_meta is not None:
            table=getattr(attrs_meta,"db_table",None)
            if table is not None:
                db_table=table
        attrs["db_table"]=db_table
        attrs["_meta"]=attrs_meta
        attrs["fields"]=fields
        if attrs_meta:
            del attrs["Meta"]
        return super().__new__(cls,name, bases, attrs,**kwargs)

class ModelBase(metaclass=ModelMetaClass):
    def __init__(self,*args,**kwargs):
        for key,value in kwargs.items():
            setattr(self,key,value)
        return super().__init__()
    def save(self):
        fields=[]
        values=[]
        for key,value in self.fields.items():
            db_column=value.db_column
            if db_column is None:
                db_column=key.lower()
            fields.append(db_column)
            value=getattr(self,key)
            values.append(str(value))
        sql = "insert {db_table}({fields}) value({values})".format(db_table=self._meta.db_table,fields=",".join(fields),values=",".join(values))
        pass
class User(ModelBase):
    name=CharField(max_length=10)
    age=InterField(min_value=0,max_value=100)

    class Meta:
        db_table="user"

    def _test(self):
        print("_test:",self.age)


if __name__=="__main__":
    user=User()
    user.name="bobby"
    user.age=23
    user._test()
    user.save()
复制代码


相关教程
          
关于我们--广告服务--免责声明--本站帮助-友情链接--版权声明--联系我们       黑ICP备07002182号