zoukankan      html  css  js  c++  java
  • 元类

    1、什么是元类?

    在python中一切皆对象,那么我们用class关键字定义的类本身也是对象;

    负责产生该对象的类叫做元类,即元类也可以简称类的类

    class Foo: #Foo=元类()

             pass

    2、为什么要用元类?

    元类是负责产生类的,所以我们学习元类或者自定义类的目的是为了控制类的产生过程,

    还可以控制对象的产生过程。

    3、怎么用

    #储备知识内置函数exec用法
    # cmd="""
    # x=1
    # y =2
    # def func(self):
    # pass
    # """
    # class_dic={}
    # exec(cmd,{},class_dic)
    # exec会执行cmd对应的字符串中的代码,将执行中产生的名字(x,y,func)丢入class_dic
    # 模仿了类定义阶段造名称空间的操作
    # print(class_dic)


    1)创建类的方法有两种
    #前提:如果说类也是对象的话,那么用class关键字去创建类的过程也是一个实例化的过程,
    #该实例化的目的是为了得到一个类,调用的是元类
    #方式一:用class关键字去创建,用默认的元类
    # class People: #People= type(.....) 造类
    # country = 'china'
    # def __init__(self,name,age):
    # self .name= name
    # self .age= age
    # def eat(self):
    # print('%s in eating'%self.name)
    #
    # peo= People ('qqc',18)
    # print(type(People )) # <class 'type'> #查看默认元类

    #创造类的3个要素 :类名 基类 类的名称空间
    # class_name='People'
    # class_bases=(object,)
    # class_dic={} #类的名称空间
    # class_body="""
    # country='China'
    # def __init__(self,name,age):
    # self.name=name
    # self.age=age
    # def eat(self):
    # print('%s is eating' %self.name)
    # """
    # exec(class_body,{},class_dic)

    #准备好累的三要素
    # print(class_name )
    # print(class_bases)
    # print(class_dic)
    # People = type(class_name ,class_bases ,class_dic ) #用type生成类People
    # print(People )
    方式二;用自定义的元类
    # class Mymeta(type):  # 只有继承了type类才能称为一个元类,否则就是一个普通自定义类
    # def __init__(self,class_name ,class_bases ,class_dic):
    # print(self ) #现在的People身份是Mymeta实例化后的对象
    # print(class_name)
    # print(class_bases)
    # print(class_dic)
    # super (Mymeta ,self).__init__(class_name ,class_bases ,class_dic)
    # 加入父类属性

    #class 自定义类的运行原理(非元类运行原理)
    #1、拿到字符串类名 class_name= People
    #2、拿到父类class_bases=(object,...)
    #3、执行类体代码,拿到类的名称空间 class_dic={} 通过exec方法
    #4、调用type 将三个元素传入,完成实例化 People= type(class_name ,class_bases ,class_dic)

    # class People(object,metaclass= Mymeta): #People =Mymeta(...) 用自定义类进行实例化
    # country = 'china'
    # def __init__(self,name,age):
    # self .name= name
    # self .age= age
    # def eat(self):
    # print('%s in eating'%self.name)
    (2)自定义元类控制类的产生过程,类的产生过程其实就是元类的调用过程
    class Mymeta(type):  # 只有继承了type类才能称为一个元类,否则就是一个普通自定义类
    # def __init__(self,class_name ,class_bases ,class_dic):
    # if class_dic .get('__doc__')is None or len(class_dic .get('__doc__').strip())==0:
    # #如果文档为空或者去空格后长度为0
    # raise TypeError ('类中必须要有文档注释,不能为空')
    # if not class_name .istitle():
    # raise TypeError ('首字母要大写')
    # super (Mymeta ,self).__init__(class_name ,class_bases ,class_dic)
    #
    # class People(object,metaclass= Mymeta): #People =Mymeta(People,object,{) 用自定义类进行实例化
    # ''' 好好 '''
    # country = 'china'
    # def __init__(self,name,age):
    # self .name= name
    # self .age= age
    # def eat(self):
    # print('%s in eating'%self.name)
    # print(People .__dict__ )
     
    (3)自定义元类控制类的调用过程,即类的实例化过程(控制类对象创建)
    储备知识:__call__
    # class Foo:
    # def __call__(self, *args ,**kwargs ):
    # print(self )
    # print(args )
    # print(kwargs )
    # pass
    # obj= Foo()
    # obj(5,6,x=1)
    # 要想让obj成为一个可调用对象,需要在该对象的类中定义__call__方法
    例题:
    class Mymeta(type):
    def __call__(self, *args ,**kwargs):
    print(self) #self 就是People
    print(args )
    print(kwargs )
    return 'tt'
    #1、造people 的空对象
    obj= self .__new__(self)
    #2、为对象初始化独有属性
    print(args ,kwargs )
    self.__init__(obj,*args ,**kwargs )
    #3、返回一个初始化好的对象
    return obj

    class Foo(object,metaclass= Mymeta): #People =Mymeta(People,object,{) 用自定义类进行实例化
    ''' 好好 '''
    country = 'china'
    def __init__(self,name,age):
    self .name= name
    self .age= age
    def eat(self):
    print('%s in eating'%self.name)
    h= Foo('qqc",6)

    #分析:调用People的目的
    #先造出People的空对象,为该对象初始化独有的属性
    obj = People ('qqc',age=123)
    print(obj.name )
    
    
     运行过程: Foo('qqc',6)在实例化时,触发了元类Mymatw中的__call__功能,把自己当成参数传给了self,'qqc',6传给了*args,**kwargs
    #然后通过__new__方法创建了空对象obj,再通过__init__方法,类Foo给对象obj初始化属性,最后返回对象obj(h)
     





  • 相关阅读:
    基于Flume做FTP文件实时同步的windows服务。
    Java代码解决ElasticSearch的Result window is too large问题
    springboot+zuul(二)------智能负载
    springboot+zuul(一)------实现自定义过滤器、动态路由、动态负载。
    Docker 快速安装&搭建 Ngnix 环境,并配置反向代理
    如何通过 Freemark 优雅地生成那些花里胡哨的复杂样式 Excel 文件?
    Elasticserach 同步索引报错:ElasticSearch ClusterBlockException[blocked by: [FORBIDDEN/12/index read-only / allow delete (api)]
    如何通过Gitalk评论插件,5分钟为你的博客快速集成评论功能
    一文教您如何通过 Docker 快速搭建各种测试环境(Mysql, Redis, Elasticsearch, MongoDB) | 建议收藏
    Docker 快速安装&搭建 Mysql 环境
  • 原文地址:https://www.cnblogs.com/quqinchao/p/9249954.html
Copyright © 2011-2022 走看看