元类
什么是元类
因为在python中一切皆对象,类实际上就是一个一个的类
type是内置的一个元类,所有的类都是由type实例化得到
class Person:
def __init__(self,name):
self.name=name
def score(self):
print('分数是100')
p=Person('nick')
如Person类也是个对象,那他一定是由一个类实例化得到,这个类,就叫元类
同理:type类是产生所有类的元类
class底层原理
通过type来直接产生类,不用class关键字了
l ={}
exec('''
school = 'oldboy'
def __init__(self,name):
self.name= name
def score(self):
print('分数是100')
''',{},l)
Person = type('Person',(object,),l) ##type产生的类
print(Person.__bases__)
# ->(<class 'object'>,)
p = Person('nick')
print(p.name)
# ->nick
class 底层就是调用type来实例化产生类(对象)
Person 类是由type实例化产生,传一堆参数
自定义元类控制类的产生
自定义元类:来控制类的产生:可以控制类名,可以控制类的继承父类,控制类的名称空间
自定义元类必须继承type>>>
class Mymeta(type):
#type(name, bases, dict) -> a new type
def __init__(self,name,bases,dic):
print(name)
print(bases)
print(dic)
class Person(object,metaclass=Mymeta):
#当python解释器遇到metaclass会去使用Mymeta去创建这个类
#这里可以把person类看成一个对象
school = 'heima'
def __init__(self,name):
self.name = name
def score(self):
print('分数是100')
p = Person('nick')
print(p.name)
结果:
# -> Person
# ->(<class 'object'>,)
# ->{'__module__': '__main__', '__qualname__': 'Person', 'school': 'heima', '__init__': <function Person.__init__ at 0x0000028A31973EA0>, 'score': <function Person.score at 0x0000028A31973F28>}
# ->nick
通过元类控制类的调用过程
控制类的调用过程,实际上在控制:对象的产生
# 触发元类的__call__,无法调用p.name
class Mymeta(type):
def __call__(self, *args, **kwargs):
# print('xxx')
return 1
class Person(object,metaclass=Mymeta):
school='zheda'
def __init__(self,name):
self.name=name
def score(self):
print('分数是100')
p=Person('nick')
print(p)
# print(p.name) ->报错
结果:1
_new_
__new__方法(第一个执行)先于__init__方法执行
__new__方法是传入类(cls),而__init__方法传入类的实例化对象(self),而有意思的是,__new__方法返回的值就是一个实例化对象(ps:如果__new__方法返回None,则__init__方法不会被执行,并且返回值只能调用父类中的__new__方法,而不能调用毫无关系的类的__new__方法)。
class A:
pass
class B(A):
def __new__(cls):
print("__new__方法被执行")
return cls.__new__(cls)
def __init__(self):
print("__init__方法被执行")
b = B()
#注意:new() 函数只能用于从object继承的新式类。
有了元类后的属性查找
class Mymeta(type): # 只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类
n = 444
def __call__(self, *args,
**kwargs): #self=<class '__main__.OldboyTeacher'>
obj = self.__new__(self)
self.__init__(obj, *args, **kwargs)
return obj
class Bar(object):
n = 333
class Foo(Bar):
n = 222
class OldboyTeacher(Foo, metaclass=Mymeta):
n = 111
school = 'oldboy'
def __init__(self, name, age):
self.name = name
self.age = age
def say(self):
print('%s says welcome to the oldboy to learn Python' % self.name)
print(
OldboyTeacher.n
) # 自下而上依次注释各个类中的n=xxx,然后重新运行程序,发现n的查找顺序为OldboyTeacher->Foo->Bar->object->Mymeta->type
1.类的属性查找顺序:先从类本身中找--->mro继承关系去父类中找---->去自己定义的元类中找--->type中--->报错
2.对象的属性查找顺序:先从对象自身找--->类中找--->mro继承关系去父类中找--->报错