一、元类
在python中一切皆对象,所以类也是一个对象,对象是由类实例化产生的,所以类也可以实例化产生。那么实例化产生类的类就是元类。
class B
def __init__(self,v)
print(type(B))
<class 'type'>
使用print(type(类))的方法可以找到类的类。
type为python内置元类,所有的类都是由type实例化产生的。
二、class底层原理分析
平时使用class + 类名的方式将类构造出来,但实际上这些类是由元类实例化产生的。type为python内置元类,类是由type实例化产生,并且传入一堆参数。
type是使用类的内置__init__方法产生类的。
# 类的源码
def __init__(cls, what, bases=None, dict=None): # known special case of type.__init__
"""
type(object_or_name, bases, dict)
type(object) -> the object's type
type(name, bases, dict) -> a new type
# (copied from class doc)
"""
pass
元类通过object_or_name, bases, dict(类名:字符串,父类,名称空间:字典)的方式产生类,可以代替class关键字的方式。
#通过type来直接产生类,不用class关键字了
l={}
exec('''
school='oldboy'
def __init__(self,name):
self.name=name
def score(self):
print('分数是100')
''',{},l)
def __init__(self,name):
self.name=name
# Person=type('Person',(object,),{'school':'oldboy','__init__':__init__})
#
Person=type('Person',(object,),l)
三、通过元类控制类的产生
通过控制类名,控制类的继承父类,控制类的名称空间的方法自定义元类,由此可以控制类的产生。
自定义元类,都要继承type元类。
class A(type):
class B(metaclass= A):
metaclass= A指定类B的元类为A。
练习:自定义元类,控制类产生,类的名称空间必须要有name字段才能创建成功,否则失败。
lass Mymeta(type):
def __init__(self,name):
if not 'name' in name:
raise TypeError('没有name字段')
class Aname(object,metaclass=Mymeta):
def __init__(self,name):
self.name = name
四、通过元类控制类的调用
通过元类控制类的调用实际上是在控制对象的产生。
class Mymeta(type):
def __call__(self, *args, **kwargs):
# print('xxx')
return 1
class Person(object,metaclass=Mymeta):
school='oldboy'
def __init__(self,name):
self.name=name
def score(self):
print('分数是100')
p=Person('nick')
print(p.name)
类的调用过程是先触发元类的__call__ ,再触发类的init方法。
练习:定义一个元类,定义一个类继承字典,使其具备点取值和赋值功能,通过元类控制对象的产生,把所有属性放在attr字典中,属性全删除。
class Mymeta(type):
def __call__(self, *args, **kwargs):
obj = self.__new__(self)
obj.__init__(*args, **kwargs)
dic = {}
dict.update(obj.__dict__)
attr = {'attr':dic}
obj.__dict__.clear()
obj.__dict__.update(attr)
class Test(dict,metaclass=Mymeta):
def __init__(self,**kwargs):
self.__dict__.update(kwargs)
def __getattr__(self, item):
return self.__dict__['attr'][item]
def __setattr__(self, key, value):
self.__dict__['attr'][key] = value
t = Test(name='lqz', age=18)
print(t.__dict__)
print(t.name)
print(t.age)
t.male = 'nan'
print(t.male)
print(t.__dict__)
五、有元类后属性查找顺序
类的属性查找顺序:先从类本身中找--->mro继承关系去父类中找---->去自己定义的元类中找--->type中--->报错
对象的属性查找顺序:先从对象自身找--->类中找--->mro继承关系去父类中找--->报错