学习到后面的实战后,回头来学习元类,突然恍然大悟,元类不管怎么使用,只是去修改类的一种手段,理解为元类创建类这个对象,思路就极其的清晰,贴上个人爬坑的代码:
#该类学习两个对象定制方法:__getattr__,__setattr__ class Model(object): #如果用点语法访问不存在的属性就会调用该方法,因为model继承dict没有定义属性,全是键值对,巧妙的通过点语法转换到获取字典的值 def __getattr__(self, key): try: print('点语法访问了某个属性'); return self[key] except KeyError: raise AttributeError(r"'Model' object has no attribute '%s'" % key) #用点语法给对象属性赋值都会走该方法 #如果Model继承的不是dict,那么可以通过__dict__获取一个对象所有属性的一个字典 def __setattr__(self, key, value): self[key] = value print(type(Model)) model = Model() print(model.__dict__) print(type(model)) #次例子是学习type动态创建类 def fn(self,name='hehda'): print('hello %s' % (name,)) print(self) #type的第一个参数是类名,第二个参数是继承的父类为元组,第三个参数是对象方法和属性为字典 HeHe = type('HeHe', (object,), {'hifn':fn}) print(type(HeHe)) hehe = HeHe() print(hehe) hehe.hifn() #次例子是学习元类来定制(创建)类 def add(self,value): self.append(value) class MHMetaClass(type): #第一个参数是元类对象,第二个参数要创建的类名,第三个是要创建的类的父类,第四个参数很重要,是类的属性和方法(请记住不是对象的属性和方法,请自行查阅廖大之前教程以作区分) def __new__(cls,name,bases,attrs): print("通过元类来创建一个类:%s,%s,%s,%s" % (cls,name,bases,attrs)) attrs['add'] = add return type.__new__(cls,name,bases,attrs) class MHList(list,metaclass=MHMetaClass): pass l = MHList() l.append(1) l.add(2) print(l) #次例子是为了验证super()的用法,以及__str__来定制对象 class F(object): def __init__(self,name,age): self.name = name self.age = age class C(F): def __init__(self,name,age,color): #廖大教程中的写法教老,新版本中可以省略super()里指定的类和对象,下面的语句就是super()获取父类,然后调用父类的__init__方法,但是我倾向于理解为super()是利用当前对象来调用父类的初始化方法 super().__init__(name,age) self.color = color #该方法会改变print的输出 def __str__(self): return "%s,%s,%s" % (self.name,self.age,self.color) c = C("刘德华",78,'绿色') print(c) #次例子就是ORM的简单实现,重要部分已做注释 class Field(object): def __init__(self,name,type): self.name = name self.type = type def __str__(self): return '<%s:%s>' % (self.__class__.__name__,self.name) class IntegerField(Field): def __init__(self,name,type='int(20)'): super().__init__(name,type) class StringField(Field): def __init__(self,name,type='varchar(20)'): super().__init__(name,type) class SchoolMetaClass(type): def __new__(cls,name,bases,attrs): mapping = dict() print('mapping:%s' % mapping) for key,value in attrs.items(): if isinstance(value, Field): print('类的属性和方法---%s:%s' % (key,value)) mapping[key] = value #移除类属性以免与对象属性发生冲突 for key in mapping.keys(): attrs.pop(key) attrs['__mapping__'] = mapping #类名和属性的映射 attrs['__table__'] = name #表名 print(attrs) return type.__new__(cls,name,bases,attrs) class BaseSchool(dict,metaclass=SchoolMetaClass): def __init__(self,**keywords): print(keywords) #继承字典,对象调用该方法传关键字参数 super().__init__(**keywords) def __getattr__(self,key): return self[key] def __setattr__(self,key,value): self[key] = value def save(self): #保存列名 fields = [] #sql语句的占位符是?,保存? parms = [] #占位符对应的具体结果,就是值的集合 args = [] for key,value in self.__mapping__.items(): fields.append(value.name) parms.append('?') args.append(getattr(self,key,None)) sql = 'insert into %s (%s) value %s' % (self.__table__,','.join(fields),','.join(parms)) print('sql:%s'% (sql)) print(str(args)) class School(BaseSchool): name = StringField('name') id = IntegerField('id') email = StringField('email') school = School(name='hehed',id='555',email='8064444') school.save() print(school.name)
Sign in to make a reply
作家大种马
学习到后面的实战后,回头来学习元类,突然恍然大悟,元类不管怎么使用,只是去修改类的一种手段,理解为元类创建类这个对象,思路就极其的清晰,贴上个人爬坑的代码: