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__方法,完成初始化

 posted on 2019-12-14 00:09  Rannie`  阅读(219)  评论(0编辑  收藏  举报
去除动画
找回动画