一 . 什么是元类
一切源自于一句话:python中一切皆为对象,而对象都是由类实例化得到的
class OldboyTeacher:
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def score(self):
print('%s is scoring' %self.name)
tea1=OldboyTeacher('egon',18,'male')
print(type(tea1))
print(type(OldboyTeacher))
# 对象tea1是调用OldboyTeacher类得到的,如果说一切皆对象,那么OldboyTeacher也是一个对象,只要是对象
# 都是调用一个类实例化得到的,即OldboyTeacher=元类(...),内置的元类是type
# 关系:
# 1. 调用元类---->自定义的类
# 2. 调用自定义的类---->自定义的对象
class关键字在帮我们创建类时,必然帮我们调用了元类OldboyTeacher=type(...),那调用type时传入的参数是什么呢?必然是类的关键组成部分,一个类有三大组成部分,分别是
1、类名class_name='OldboyTeacher'
2、基类们class_bases=(object,)
3、类的名称空间class_dic,类的名称空间是执行类体代码而得到的
调用type时会依次传入以上三个参数
class_name = 'OldboyTeacher'
class_bases = (object,)
class_dic = {}
class_body = """
school = 'Oldboy'
def __init__(self,name,age):
self.name = name
self.age = age
"""
# exec(类体代码(字符串class_body) , 全局作用域(空{}),局部作用域(class_dic))
exec(class_body, {}, class_dic)
OldboyTeacher = type(class_name, class_bases, class_dic)
print(OldboyTeacher)
t1 = OldboyTeacher('egon', 18)
print(t1.school)
不依赖class 关键字创建一个自定义类
class Mymeta(type):
def __call__(self, *args, **kwargs):
# 产生一个空对象(OldboyStudent)
stu_obj = self.__new__(self)
# 执行__init__ ,将参数传入stu_obj 对象中
self.__init__(stu_obj, *args, **kwargs)
# 返回 stu_obj 对象
return stu_obj
class OldboyStudent(object, metaclass=Mymeta):
school = 'Oldboy'
def __init__(self, name, age):
self.name = name
self.age = age
stu = OldboyStudent('hgq', 20) # 触发OldboyStudent的类(元类)中的__call__函数
print(stu.__dict__)
控制类的产生
class Mymeta(type):
def __init__(self, class_name, class_bases, class_dic):
if class_name.islower():
raise TypeError('类名必须为驼峰体')
doc = class_dic.get('__doc__')
if doc is None or len(doc) == 0 or len(doc.strip('\n ')) == 0:
raise TypeError('类体中必须有文档注释,并且文档注释不能为空')
class OldboyStudent(object, metaclass=Mymeta):
"""
老男孩学生类
"""
school = 'Oldboy'
def __init__(self, name, age):
self.name = name
self.age = age
属性查找顺序
以对象的类为起始---类的父类---父类的父类---直到object---再是类的元组---type(没有则报错)
class Mymeta(type): # 但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类
# n=444
def __call__(self, *args, **kwargs): #self=OldboyTeacher这个类
# 1. 先产生一个空对象
tea_obj = self.__new__(self) # tea_obj是OldboyTeacher这个类的对象
# print(self.__new__ is object.__new__)
# tea_obj=object.__new__(self)
# 2. 执行__init__方法,完成对象的初始属性操作
self.__init__(tea_obj, *args, **kwargs)
# 3. 返回初始化好的那个对象
return tea_obj
class Bar:
# n = 33
pass
class Foo(Bar):
# n = 222
pass
class OldboyTeacher(Foo, metaclass=Mymeta): # OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...})
# n = 111
school = 'Oldboy'
def __init__(self, name, age, sex):
self.name = name #None.name='egon'
self.age = age
self.sex = sex
def score(self):
print('%s is scoring' % self.name)
def __new__(cls, *args, **kwargs):
# print('=====>')
return super().__new__(cls)
tea1 = OldboyTeacher('egon', 18, 'male')
# print(tea1)
print(tea1.__dict__)
# print(OldboyTeacher.n)
# print(object.__new__)