zoukankan      html  css  js  c++  java
  • 元类

    什么是元类:

    源自一句话:在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(OldboyTeacher))
     对象tea1是调用OldboyTeacher类得到的,如果说一切皆对象,那么OldboyTeacher也是一个对象,只要是对象
    都是调用一个类实例化得到的,即OldboyTeacher=元类(...),内置的元类是type


     关系:
    1. 调用元类---->自定义的类
    2. 调用自定义的类---->自定义的对象




    class关键字创建自定义类的底层的工作原理,分为四步:

    1. 先拿到类名:'OldboyTeacher'
    2. 再拿到类的基类们:(object,)
    3. 然后拿到类的名称空间???(执行类体代码,将产生的名字放到类的名称空间也就是一个字典里,补充exec)
    4. 调用元类实例化得到自定义的类: OldboyTeacher=type('OldboyTeacher',(object,),{...})
    class OldboyTeacher: #OldboyTeacher=type(...)
    school = 'Oldboy'
    def __init__(self,name,age,sex):
    self.name=name
    self.age=age
    self.sex=sex

    def score(self):
    print('%s is scoring' %self.name)
    print(OldboyTeacher)


    不依赖class关键字创建一个自定义类:

    # 1. 拿到类名
    class_name='OldboyTeacher'
    #2. 拿到类的基类们:(object,)
    class_bases=(object,)
    #3. 拿到类的名称空间
    class_dic={}
    class_body="""
    school = 'Oldboy'

    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(class_body,{},class_dic)
    print(class_dic)
    #4. 调用type得到自定义的类
    OldboyTeacher=type(class_name,class_bases,class_dic)

    print(OldboyTeacher)
    # print(OldboyTeacher.school)
    # print(OldboyTeacher.score)

    tea1=OldboyTeacher('egon',18,'male')
    print(tea1.__dict__)

    自定义元类控制类的产生:
    # 控类的产生
    # 1.类名必须用驼峰体
    # 2.类体必须有文档注释,且文档注释不能为空
    class Mymeta(type): #但凡继承了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(' ')) == 0:
    raise TypeError('类体中必须有文档注释,且文档注释不能为空')

    class OldboyTeacher(object,metaclass=Mymeta): #OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...})
    school = 'Oldboy'

    def __init__(self,name,age,sex):
    self.name=name
    self.age=age
    self.sex=sex

    def score(self):
    print('%s is scoring' %self.name)
    print(OldboyTeacher.__dict__)


    自定义元类控制类的调用过程:
    # 实例化OldboyTeacher,或者说调用OldboyTeacher会
    # 1. 先产生一个空对象
    # 2. 执行__init__方法,完成对象的初始属性操作
    # 3. 返回初始化好的那个对象
    # 推导:调用OldboyTeacher(...)就是在调用OldboyTeacher的类中的__call__,那么在该__call__中就需要做上述三件事

    #自定义元类来控制类的调用(即类的实例化过程)

    class Mymeta(type): #但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类
    def __call__(self, *args, **kwargs): #self=OldboyTeacher这个类,args=('egon',18,'male'),kwargs={}
    # 1. 先产生一个空对象
    tea_obj=self.__new__(self) #tea_obj是OldboyTeacher这个类的对象
    # 2. 执行__init__方法,完成对象的初始属性操作
    self.__init__(tea_obj,*args,**kwargs)
    # print(tea_obj.__dict__)
    tea_obj.__dict__={('_%s__%s' %(self.__name__,k)):v for k,v in tea_obj.__dict__.items()}
    # 3. 返回初始化好的那个对象
    return tea_obj

    class OldboyTeacher(object,metaclass=Mymeta): #OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...})
    school = 'Oldboy'

    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') # 会触发OldboyTeacher的类(即元类)中的__call__函数
    # print(tea1)
    print(tea1.__dict__)







  • 相关阅读:
    IOS和Android支持的音频编解码
    IOS XIB Cell自适应高度实现
    IOS竖屏应用单个页面横屏的解决办法
    FMDB读取Datetime类型值为1970的问题
    一些IOS开发中的小技巧
    IOS的一些小技巧
    Static块详解
    Hadoop学习笔记3---安装并运行Hadoop
    Hadoop学习笔记2---配置详解
    同一账户在同一时间 只能登陆一次
  • 原文地址:https://www.cnblogs.com/zhangpang/p/9580392.html
Copyright © 2011-2022 走看看