type生元类,元类生类,类生对象
换句话就是

道系元类解读,生就完了
话不多说上代码来理解:
def fn1(self,name='world'):
print('Hello,%s'%name)
def fn2(self,name='world'):
print('Hi,%s'%name)
Hello = type('Hello',(object,),dict(say_hi=fn1,hi='hello'))
Hi = type('Hello',(object,),dict(say_hi=fn2,hi='hi'))
# 生成Hello类的对象
hello1 = Hello()
hello1.say_hi()
print(hello1.hi)
print(hello1)
print('-'*50) # 华丽分割线
# 生成Hi类的对象
hello2 = Hi()
print(hello2.hi)
hello2.say_hi()
print(hello2)
结果:
Hello,world hello <__main__.Hello object at 0x0000022EBA06EBA8> -------------------------------------------------- hi Hi,world <__main__.Hello object at 0x0000022EBA06EC50>
type()可以产生类,那么结果就证明了,他可以定制类的名称属性方法等。可以用于创造万物。
django中的ORM,大致思路如下:
class Field(object):
def __init__(self, column_type, primary_key, default):
self.column_type = column_type
self.primary_key = primary_key
self.default = default
class StringField(Field):
def __init__(self, column_type='varchar(32)', primary_key=False, default=None):
super().__init__(column_type, primary_key, default)
class IntegerField(Field):
def __init__(self,column_type='int', primary_key=False, default=0):
super().__init__(column_type, primary_key, default)
class MyMetaClass(type):
def __new__(cls, class_name,class_bases,class_attrs):
if class_name == 'Models':
return type.__new__(cls,class_name,class_bases,class_attrs)
table_name = class_attrs.get('table_name',class_name)
primary_key = None
mappings = {}
for k,v in class_attrs.items():
if isinstance(v,Field):
mappings[k]=v
if v.primary_key:
if primary_key:
raise TypeError('一张表只能有一个主键')
primary_key = k
print(class_attrs)
for k in mappings.keys():
class_attrs.pop(k)
if not primary_key:
raise TypeError('一张表必须有主键')
class_attrs['table_name'] = table_name
class_attrs['primary_key'] = primary_key
class_attrs['mappings'] = mappings
print(class_attrs)
return type.__new__(cls, class_name,class_bases,class_attrs)
class Models(dict,metaclass=MyMetaClass):
def __init__(self,**kwargs):
super().__init__(**kwargs)
def __getattr__(self, item):
return self.get(item,'没有该键')
def __setattr__(self, key, value):
self[key] = value
@classmethod
def select(cls,**kwargs):
pass
if __name__ == '__main__':
class Teacher(Models):
table_name = 'author'
id = IntegerField(primary_key=True)
name = StringField()
a = Teacher(id=12,name='xxx')
print(a)
print(a.name)
结果:
{'__module__': '__main__', '__qualname__': 'Teacher', 'table_name': 'author', 'id': <__main__.IntegerField object at 0x0000021E7680ECF8>, 'name': <__main__.StringField object at 0x0000021E76814438>}
{'__module__': '__main__', '__qualname__': 'Teacher', 'table_name': 'author', 'primary_key': 'id', 'mappings': {'id': <__main__.IntegerField object at 0x0000021E7680ECF8>, 'name': <__main__.StringField object at 0x0000021E76814438>}}
{'id': 12, 'name': 'xxx'}
xxx
可以理解为:元类metaclass,是继承了type来控制其他类的产生的工具
然后用MyMetaClass来控制继承Model类的Teacher类,在生成类的实例的过程中,将类的同名属性id、name打包进mappings属性中,使得可以通过getattr来获取他自身字典中的值。可能还是不太明白那就继续看:
class Models(dict):
def __init__(self,**kwargs):
super().__init__(**kwargs)
def __getattr__(self, item):
return self.get(item,'没有该键')
def __setattr__(self, key, value):
self[key] = value
@classmethod
def select(cls,**kwargs):
pass
if __name__ == '__main__':
class Teacher(Models):
table_name = 'author'
id = IntegerField(primary_key=True)
name = StringField()
a = Teacher(id=12,name='xxx')
print(a)
print(a.name)
结果:
{'id': 12, 'name': 'xxx'}
<__main__.StringField object at 0x000001BD9825EDD8>
此时没有元类MyMetaClass的控制,a.name,获取到的是Teacher类的属性,是一个StringField的对象,而不是他本身字典的键对应值,问题就是这里,元类的引入就是为了解决这种问题,因为a.name会首先找本类的属性,再找父类的属性,如果在这过程中找到了,就不会继续查询,也根本不会调用重写的__getattr__方法。所以在类的创建时,通过把原先的属性隐藏起来,可以让对象去触发getattr得到自身包含的值。
本文深入探讨Python元类的工作原理,展示如何使用元类自定义类的生成过程,特别聚焦于Django ORM的设计思路,解释如何通过元类实现类属性的动态管理和数据库表的映射。
1745

被折叠的 条评论
为什么被折叠?



