zoukankan      html  css  js  c++  java
  • day 29 什么是元类、class底层原理分析、通过元类来控制类的产生、通过元类控制类的调用过程、有了元类之后的属性查找

    元类

    #一切皆对象:类实际上一个一个对象
    #Person类也是个对象,那他一定是由一个类实例化得到,这个类,就叫元类
    #type是内置的一个元类,所有的类都是由type实例化得到

    #产生类的类,叫元类
    class Person:
    def __init__(self,name):
    self.name=name
    def score(self):
    print('分数是100')

    p=Person('nick')

    # a=Person
    # p1=a('nick')
    # print(p1.name)

    如何找元类?
    # print(type(p))
    #同理:type类是产生所有类的元类
    # print(type(Person))
    print(type(dict))
    print(type(list))
    print(type(str))
    print(type(object))
    print(type(type))


    class 底层原理
    #class 类名 会把类构造出来,实际上是:元类实例化产生类这个对象,类实例化产生对象,一定是: 类名()#Person 类是由type实例化产生,传一堆参数
    #class 底层就是调用type来实例化产生类(对象)
    #type()  调用类的__init__方法???
    #type(object_or_name, bases, dict)
    object_or_name:类的名字,是个字符串
    bases:是它的所有父类,基类,是一个元组
    dict:名称空间,是一个字典

    l={}
    exec('''
    school='oldboy'
    def __init__(self,name):
    self.name=name
    def score(self):
    print('分数是100')
    ''',{},l)
    Person=type('Person',(object,),l)
    或者
    def __init__(self,name):
    self.name=name
    Person=type('Person',(object,),{'school':'oldboy','__init__':__init__})



    #print(Person.__dict__)
    #print(Person.__bases__)
    # p=Person('nick')
    # print(p.name)
    # print(p.__dict__)



    # class Person:
    # school='oldboy'
    # def __init__(self,name):
    # self.name=name
    # def score(self):
    # print('分数是100')
    # a=Person
    #
    # p=Person('nick')

    exec()的用法
    # l={}
    # exec('''
    # school='oldboy'
    # def __init__(self,name):
    # self.name=name
    # def score(self):
    # print('分数是100')
    # ''',{},l)

    # print(l)
    # g={ 'x':1,'y':2}
    # l={}
    # exec('''
    # global x
    # x=100
    # z=200
    # m=300
    # ''',g,l)
    # print(g)
    # print(l)

    # x=1
    # y=2
    # def test():
    # global x
    # x = 100
    # z = 200
    # m = 300


    通过元类来控制类的产生
    自定义元类来控制类的产生,可以控制类名,可以控制类的继承父类,控制类的名称空间

    自定义元类必须继承type,写一个类继承type 这种类都叫元类

    class Mymeta(type):
    def __init__(self,name,bases,dic):
    # self 就是Person类
    print(name)
    print(bases)
    print(dic)
    #练习一:加限制 控制类名必须以sb开头
    if not name.startswith('sb'):
    raise Exception('类名没有以sb开头')




    class Person(object,metaclass=Mymeta): #metaclass=Mymeta 指定这个类生成的时候,用自己写的Mymeta这个元类
         '''
    注释
    '''
    school='oldboy'
    def __init__(self,name):
    self.name=name
    def score(self):
    print('分数是100')

    p=Person()
    #练习二:类必须加注释
    class Mymeta(type):
    def __init__(self,name,bases,dic):
    print(self.__dict__['__doc__'])
    doc=self.__dict__['__doc__']
    if not doc:
    #没有加注释
    raise Exception('你的类没有加注释')
    class Person(object,metaclass=Mymeta):
    '''
    我加了注释
    '''
    school='oldboy'
    def __init__(self,name):
    self.name=name
    def score(self):
    print('分数是100')




    通过元类控制类的调用过程
    #要使用到__call__
    #控制类的调用过程,本质上在控制:对象的产生
    class Mymeta(type):
    def __call__(self, *args, **kwargs):
    print('xxx')

    return 1

    class Person(object,metaclass=Mymeta):
    school='oldboy'
    def __init__(self,name):
    self.name=name
    def score(self):
    print('分数是100')

    p=Person('nick')
    print(p.name)
    #打印xxx,并且p没有name属性


    class Person():
    school='oldboy'
    def __init__(self,name):
    self.name=name
    def score(self):
    print('分数是100')
    def __call__(self, *args, **kwargs):
    print('xxxx')

    p=Person('nick') #自动触发init的执行
    p() #先触发元类的__call__,也就是说__call__实例化的对象或者实例化的类加括号调用时才会触发__call__
    #__new__方法
    #练习:把对象中的所有属性都设置成私有
    分析
    class Mymeta(type):
    def __call__(self, *args, **kwargs):
    #self 是Person这个类
    # print(args)
    # print(kwargs)
    # return self(*args) #这里不行,会递归

    #实例化产生一个Person类的对象,借助__new__来产生,需要把类传过去,才能产生对象
    #obj 是Person类的对象,只不过是空的
    obj=object.__new__(self)
    #或者 obj=self.__new__(self)
             #调用__init__方法完成初始化
    #类来调用__init__方法,就是个普通函数,有几个参数就穿几个惨
    self.__init__(obj,*args, **kwargs)
    #对象来调用__init__方法,对象的绑定方法,会把自身穿过来
    obj.__init__(*args, **kwargs)
    print(obj)
    return obj


    class Person(object, metaclass=Mymeta):
    school = 'oldboy'
    def __init__(self, name):
    self.name = name
    def score(self):
    print('分数是100')
    p = Person(name='nick')
    print(p)
    print(p.name)

    #把对象所有的属性都变成私有
    class Mymeta(type):
    def __call__(self, *args, **kwargs):
    obj=object.__new__(self)
    obj.__init__(*args, **kwargs)
    # print(obj.__dict__)
    obj.__dict__={ '_%s__%s'%(self.__name__,k):v for k,v in obj.__dict__.items()}
    # print(obj.__dict__)
    return obj

    class Person(object, metaclass=Mymeta):
    school = 'oldboy'
    def __init__(self, name):
    self.name = name
    def score(self):
    print('分数是100')
    p = Person(name='nick')
    print(p.__dict__)
    print(p.name)
    # print(p)
    # print(p.name)

     

    有了元类之后的属性查找

    对象最高查找到object
    类最高查找到type




     
  • 相关阅读:
    多个tab切换demo
    react添加和删除定时器的地方
    编写C语言的两种方法----Visual Studio/CodeBlocks
    C++学习笔记---引用的本质
    C++学习笔记---指针
    C++学习笔记---数据类型
    博客园皮肤SimpleMemory深色风格皮肤
    SQL DELETE语句如何让表使用别名的方法
    Asp.Net实现局部刷新,ScriptManager和UpdatePanel控件的使用
    由于可能不会将凭据发送到远程计算机,因此将不会进行连接。若要获得协助,请与您的系统管理员联系。(转)
  • 原文地址:https://www.cnblogs.com/wwei4332/p/11454150.html
Copyright © 2011-2022 走看看