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列表去父类中找---报错、

posted @ 2019-09-16 19:59  ZJJJJJJJ  阅读(153)  评论(0编辑  收藏  举报