zoukankan      html  css  js  c++  java
  • 面向对象——元类

    1、什么是元类

    元类:产生类的类

    # 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(tea1))
    # print(type(OldboyTeacher))

    对象tea1是调用OldboyTeacher类得到的,如果说一切皆对象,那么OldboyTeacher也是一个对象,只要是对象
    都是调用一个类实例化得到的,即OldboyTeacher=元类(...),内置的元类是type

    2、关系:

    ①调用元类————》自定义的类
    ②调用自定义的类————》自定义的对象

    3、不依赖class关键字创建一个自定义的类
    ①拿到类名

    class_name='OlaboyTeacher'

    ②拿到类的基类们

    calssbases=(object,)


    ③拿到类的名称空间

    class = {}
    class_body = """
    school = 'Oldboy'
    def __init__(self ,name,age,sex)
    	self.name = name
    	self.age = age
    	self.sex = sex
    """
    exec(class_body,{},class_dic)
    print(class_dic)

    ④调用type得到自定义的OldboyTeacher=type(‘OldboyTeacher’,(object,),{…})惊讶

    OldboyTeacher=type(class_name,class_bases,class_dic)
    print(OldboyTeacher)
    tea1=OldboyTeache('egon',18,'male')
    print(tea1.__dicet__)

    自定义的类的三个组关键组成部分:
    1、类名

    2、类的基类们

    3、类的名称空间

    模板

    # class Mymeta(type): #但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类
    #     def __init__(self,class_name,class_bases,class_dic):
    #         print(self)
    #         print(class_name)
    #         print(class_bases)
    #         print(class_dic)
    #
    # 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)

    按类的产生:

    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__)

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

    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__)

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

  • 相关阅读:
    NGUI Sprite 和 Label 改变Layer 或父物体后 未更新深度问题
    unity销毁层级物体及 NGUI 深度理解总结
    unity 2d 和 NGUI layer
    关于NGUI与原生2D混用相互遮盖的问题心得
    CentOS7为firewalld添加开放端口及相关操作
    Python 操作redis有序集合(sorted set)
    win10下安装redis 服务
    python2/3中 将base64数据写成图片,并将图片数据转为16进制数据的方法、bytes/string的区别
    解决最小化安装Centos7后无法上网的问题,以及安装成功后的基本配置
    在mysql中使用group by和order by取每个分组中日期最大一行数据,亲测有效
  • 原文地址:https://www.cnblogs.com/king-home/p/10788312.html
Copyright © 2011-2022 走看看