目录
元类:用class关键字定义的类本身是一个对象。
基于此,负责产生该对象的类称之为元类(类的类),内置的元类为type。
控制类调用的过程(元类体使用__call__)
属性查找顺序
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def score(self):
print('%s is scoring' % self.name)
p = People('name', 18)
print(type(p))
print(type(People))
'''
对象是调用类的到的,若一切皆对象,则类也是一个对象。
且对象都是调用类实例化而来,即 People = 元类(……);内置的元类为type
关系:
1.调用元类---》自定义的类
2.调用自定义的类--->自定义的对象
class关继字底层工作原理(4步):
1.拿到类名'People'
2.拿到基类:(object,)
3.拿到类的名称空间
4.调用元类实例化的到自定义的类
People = type('People',(object,),{……})
自定义类的三个关键组成部分:
1.类名
2.类的基类
3.类的名称空间
'''
# 不依赖class关键字创建一个自定义类
# 1.类名
class_name = 'People'
# 2,类的基类
class_bases = (object,)
# 3.类的名称空间
class_dic = {}
# 4.类的执行代码块
class_body = """
school = 'college'
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def score(self):
print('%s is scoring' %self.name)
"""
# exec(object,globals,locals) exec(执行对象,全局容器{必须为字典},本地容器{任何映射对象})
# exec 返回值永远为 None。
exec(class_body, {}, class_dic)
# 获取类的名称空间
print(class_dic)
# 5.调用tyoe的到自定义的类
people = type(class_name, class_bases, class_dic)
print(people.__dict__)
'''自定义元类来控制类的产生 (通过__init__) '''
# 模板
class Mymeta(type): # 但凡继承了type的类,称之为自定义元类
def __init__(self,class_name,class_bases, class_dic):
print(self)
print(class_name)
print(class_bases)
print(class_dic)
# People = Mymeta('People',(object,),{……})
class People(object,metaclass=Mymeta):
def __init__(self, name, age):
self.name = name
self.age = age
def score(self):
print('%s is scoring' % self.name)
# 控制类的产生:
# 1.类名必须用驼峰体
# 2.类体必须有文档注释,且不能为空
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('类体中必须有文档注释,且不能为空')
# People = Mymeta('People',(object,),{……})
class People(object, metaclass=Mymeta):
'''
111
'''
def __init__(self, name, age):
self.name = name
self.age = age
def score(self):
print('%s is scoring' % self.name)
'''
# 控制类调用的过程
# 实例化过程:
# 1. 先产生一个空对象
# 2. 执行__init__方法,完成对象的初始属性操作
# 3. 返回初始化好的那个对象
#
# 总结:对象之所以可以调用,是因为对象的类中有一个函数__call__
# 推导:如果一切皆对象,那么类也是一个对象,该对象之所可以调用,肯定是这个对象的类中也定义了一个函数__call__
'''
class Mymeta(type):
def __call__(self, *args, **kwargs): # self=People这个类,args=('name',18,'male'),kwargs={}
# 1. 先产生一个空对象
#__new__ 是在__init__之前被调用的特殊方法
# __new__是用来创建对象并返回之的方法
p_obj = self.__new__(self) # p_obj是People这个类的对象
# 2. 执行__init__方法,完成对象的初始属性操作
self.__init__(p_obj, *args, **kwargs)
# 3. 返回初始化好的那个对象
return p_obj
# People = Mymeta('People',(object,),{……})
class People(object, metaclass=Mymeta):
'''
111
'''
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
def score(self):
print('%s is scoring' % self.name)
p = People('name', 18, 'male') # 会触发OldboyTeacher的类(即元类)中的__call__函数
print(p)
print(p.__dict__)
'''
属性查找顺序:
1、对象层,基于mro列表的查找
2、元类层
对象的类-》父类-》父父类……——》object类-》元类(自定义)—》type
'''
class Mymeta(type):
n = 444
def __call__(self, *args, **kwargs):
# self=
obj = self.__new__(self)
print(self.__new__ is object.__new__) # True
class Bar(object):
n = 333
# def __new__(cls, *args, **kwargs):
# print('Bar.__new__')
class Foo(Bar):
n = 222
# def __new__(cls, *args, **kwargs):
# print('Foo.__new__')
class Teacher(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)
# def __new__(cls, *args, **kwargs):
# print('Teacher.__new__')
Teacher('egon', 18)
# 触发Teacher的类中的__call__方法的执行,进而执行self.__new__开始查找