9.3(day29)元类,class关键字底层原理,元类控制类产生,有了元类的属性查找顺序
元类
# 元类是什么
# 一切皆对象,类也是一个对象,是有一个类实例化产生的
# 这个类就是元类 也就是产生类的类
# 如何找元类
# print(type(类名))
# class <type>
# type是一个内置的元类,所有的类都是由type实例化得到的
class关键字的底层原理
# class关键字的底层原理
# class 类名 会把类构造出来
# 实际上是元类实例化产生类这个对象
# 类实例化产生对象,一定是:类名()
# type __init__方法
# type(object_or_name,bases,dict)
# object_or_name:类名,字符串类型
# bases:所有父类,基类,元组类型
# dict:名称空间,字典类型
# 例
# class Admin:
# school = 'oldboy'
# def __init__(self,name):
# self.name=name
# def score(self):
# print('your score is 0')
#
# A = Admin('zjh')
# 如何将 def __init__(self,name):
# self.name=name
# def score(self):
# print('your score is 0')
# 变为字典呢
# 需要用到exec()方法了
# exec()方法的使用
# 三个参数
# 第一个为字符串,第二个为全局名称空间,第三个为局部名称空间
l = {}
exec('''
school = 'oldboy'
def __init__(self,name):
self.name=name
def score(self):
print('your score is 0')
''',{},l)
print(l)
# 第一种方式:exec方法生成名称空间字典并导入
type('Admin',(object,),l)
# 第二种方式:直接写入
# {'school':'oldboy','__init__':__init__,'score':score}
Admin = type('Admin',(object,),l)
print(Admin.__dict__)
A = Admin('zjh')
print(A.score())
# 所以说,class底层就是调用type来实例化产生类(对象)
通过元类控制类的产生
# 通过元类来控制类的生成
# 可以控制类名,继承关系,名称空间
# type
# 自定义元类必须继承type,写一个类继承type 这种类就叫元类
# class My(type):
# # def __init__(self,*args,**kwargs):
# # print(args)
# # print(kwargs)
# def __init__(self,name,bases,dic):
# # self就是Admin类
# print(name)
# print(bases)
# print(dic)
# # 增加限制,如以什么开头
# if not name.startswith('sb'):
# raise Exception('类名错误')
# # 类必须加注释
# if not self.__dict__['__doc__']:
# raise Exception('没有注释')
# metaclass = My 指定这个类生成的时候,用自己写的 My这个元类,而不用type
# class sb_Admin(object,metaclass=My):
# '''
# 注释
# '''
# school = 'oldboy'
# def __init__(self,name):
# self.name=name
# def score(self):
# print('your score is 0')
# A = Admin()
# 方法和类的注释使用三引号
通过元类控制类的产生过程
# 通过元类来控制类的生成
# 可以控制类名,继承关系,名称空间
# type
# 自定义元类必须继承type,写一个类继承type 这种类就叫元类
# class My(type):
# # def __init__(self,*args,**kwargs):
# # print(args)
# # print(kwargs)
# def __init__(self,name,bases,dic):
# # self就是Admin类
# print(name)
# print(bases)
# print(dic)
# # 增加限制,如以什么开头
# if not name.startswith('sb'):
# raise Exception('类名错误')
# # 类必须加注释
# if not self.__dict__['__doc__']:
# raise Exception('没有注释')
# metaclass = My 指定这个类生成的时候,用自己写的 My这个元类,而不用type
# class sb_Admin(object,metaclass=My):
# '''
# 注释
# '''
# school = 'oldboy'
# def __init__(self,name):
# self.name=name
# def score(self):
# print('your score is 0')
# A = Admin()
# 方法和类的注释使用三引号
# 通过元类控制类的产生过程
# __call__
# class My(type):
# def __call__(self,*args,**kwargs):
# print('xxx')
# print(args)
# print(kwargs)
# return 1
# __new__,产生空对象
# self.sb_Admin这个类,通过实例化产生sb_Admin类的对象
# 借助__new__来产生,需要把类传过去
# obj = object.__new__(self)
# 调用__init__方法完成初始化
# obj.__init__(*args,**kwargs) # 对象调用
# print(obj)
# return obj
# class sb_Admin(object,metaclass=My):
# '''
# 注释
# '''
# school = 'oldboy'
# def __init__(self,name):
# self.name=name
# def score(self):
# print('your score is 0')
# def __call__(self,*args,**kwargs):
# print('xxxxx')
# A = sb_Admin(name= 'zjh')
# 先触发元类的__call__
# print(A.name)
# 生成对象先触发元类的__call__,生成一个空的对象,然后返回类中增加属性方法
# 练习:把所有属性变成私有的
class My(type):
def __call__(self,*args,**kwargs):
obj = object.__new__(self)
obj.__init__(*args,**kwargs) # 对象调用
obj.__dict__ = {'_%s__%s'%(self.__name__,k):v for k,v in obj.__dict__.items()}
print(obj.__dict__)
return obj
class sb_Admin(object,metaclass=My):
school = 'oldboy'
def __init__(self,name):
self.name=name
def score(self):
print('your score is 0')
def __call__(self,*args,**kwargs):
print('xxxxx')
A = sb_Admin(name= 'zjh')
# print(A.name)
有了元类的属性查找顺序
类的属性查找顺序:对象自身---类---根据mro列表去父类中找---去自己定义的元类中找---type---报错
对象的属性查找顺序:对象自身---类---根据mro列表去父类中找---报错、