zoukankan      html  css  js  c++  java
  • 元类

    MetaClass元类

    一 什么是元类?

    类的类(元类)就是type,其实type就是元类;
    

    为什么要使用元类?

    元类可以控制类的创建过程
    

    type() 函数更适合于动态地创建相对简单的类,如果要创建更复杂的类,则需要通过 MetaClass(元类)的方式。

     MetaClass(元类),简单的理解,就是创建类的类,即创建类之后,再由类来创建实例进行应用。
    使用元类可以在创建类时动态修改类定义。
    为了使用元类动态修改类定义,程序需要先定义元类。
    

    注意,不要从字面上去理解元类的含义,事实上,MetaClass 中的 Meta 这个词根,起源于希腊语词汇 meta,包含“超越”和“改变”的意思。

    定义元类时,需令其继承与 type 类,且默认的命名习惯是,让类名以 MetaClass 结尾。不仅如此,元类中需要定义并实现 __new__() 方法(一定要有返回值)。因为元类在创建类时,该 __new__() 方法将会被调用,用来生成新建的类。

    之所有要求元类继承 type 并实现 __new__() 方法,是因为在创建类时,内部调用了 type 的 __new__() 方法为这个类分配内存空间,当内存分配完成后,便会调用 type 的 __init__ 方法初始化

    #一切皆对象
    # list1 = []  #list1 = list([])
    # print(type(list1))  #<class 'list'>
    
    #自定义一个类
    class Chinese(object):
        country = 'china'
        def __init__(self,name,age):
            self.name = name
            self.age = age
    

    所有的对象都是实例化或者说调用类而得到的(调用类的过程称为类的实例化),比如对象obj是调用类Chinese得到的

    obj = Chinese('leti',18,)
    print(type(obj))
    print(Chinese)   # 类本质上也是一个对象,因为在python中 一切皆对象 ;
    print(type(Chinese))  #<class 'type'>
    

    如果一切皆为对象,那么类Chinese本质也是一个对象,既然所有的对象都是调用类得到的,那么Chinese必然也是调用了一个类得到的,这个类称为元类

    于是我们可以推导出===>产生Chinese的过程一定发生了:Chinese=元类(..…)

    print(type(Chinese))  #结果为<class 'type'>,证明是调用了type这个元类而产生的Chinese,即默认的元类为type
    

    二 class关键字创建类的流程分析

    上文我们基于python中一切皆为对象的概念分析出:我们用class关键字定义的类本身也是一个对象,负责产生该对象的类称之为元类(元类可以简称为类的类),内置的元类为type

    class关键字在帮我们创建类时,必然帮我们调用了元类Chinese=type(..…),那调用type时传入的参数是什么呢?必然是类的关键组成部分,一个类有三大组成部分,分别是

    1、类名class_name='Chinese'

    2、基类们class_bases=(object,)

    3、类的名称空间class_dic,类的名称空间是执行类体代码而得到的

    调用type时会依次传入以上三个参数

    综上,class关键字帮我们创建一个类应该细分为以下四个过程

    三 自定义元类控制类

    一个类没有声明自己的元类,默认他的元类就是type,除了使用内置元类type,我们也可以通过继承type来自定义元类,然后使用MetaClass关键字参数为一个类指定元类

    class MyMetaClass(type):  #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类
    
        def __init__(self,class_name,class_bases,class_dict):
            # print(class_name)  #User
            # print(class_bases)  #(<class 'object'>,)
            # print(class_dict)  #{'__module__': '__main__', '__qualname__': 'User', 'country': 'china', '__init__': <function User.__init__ at 0x00000203F139FAF8>}
            if not class_name.istitle():
                raise NameError('类的首字母必须大写')
    
            if not class_dict.get('__doc__'):
                raise TypeError('必须写注释')
            # 必须将类中的类名、类的基类、类的名称空间,一并返回给 type中的__init__
            super().__init__(class_name,class_bases,class_dict)
    
    
    class User(object,metaclass=MyMetaClass):
        """
        必须写注释
        """
        country = 'china'
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
    p = User('leti','18')
    
    

    自定义元类可以控制类的产生,类的产生过程其实就是元类的调用过程

    即Chinese = MyMetaClass('Chinese',(object),{名称空间})

    调用MyMetaClass会先产生一个空对象Chinese,然后连同调用MyMetaClass括号内的参数一同传给MyMetaClass下的__init__方法,完成初始化

  • 相关阅读:
    LeetCode105 从前序遍历和中序遍历构造二叉树
    LeetCode61 扑克牌中的顺子
    LeetCode141 环形链表
    LeetCode103 二叉树的锯齿形层次遍历
    509 斐波那契数
    剑指29 顺时针打印矩阵
    malloc分配内存2种方式:brk和mmap
    Python学习第139天(Django的分页器(paginator))
    Python学习第138天(Django的用户认真组件)
    Python学习第137天(admin部分参数补充)
  • 原文地址:https://www.cnblogs.com/kai-/p/12037893.html
Copyright © 2011-2022 走看看