美文网首页
Python metaclass/type 原理详解

Python metaclass/type 原理详解

作者: 虐心笔记 | 来源:发表于2020-04-05 13:16 被阅读0次

    在学习 metaclass 之前先了解一下 type() 和 isinstance() 函数的用法。

    内置函数 type()、isinstance()

    type()

        主要有两个功能:1.查看变量(对象)的类型。2.动态创建一个类 class,对你没有看错。

    示例1: 当传入一个参数或者对象时,返回这个对象的类型

        一般type() 函数都是用来检查对象类型的,从示例可以看出跟 object.__class__ 的功能是一致的,都是返回对象的类型

    示例2: 动态创建一个类

    class type(name, bases, dict)

    name: 要创建的类型
    bases: 要创建的类的基类, Python由于允许多继承,这里是一个元组类型
    dict: 要创建类的属性,dictionary类型

        上面的类是通过 Person =type('Person', (object,), dict(name='angst')) 创建了一个类 classVariable, 再通过classVariable() 创建了一个实例a。从上面的示例可以看出,两种创建的类是一致的,可以看输出结果类型都是一致的。在一般正常情况下都是通过 class XXX 来定义一个类。但是,type()也是允许动态创建类的,Python是一种解释性的动态语言

    isinstance()

    isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()

    isinstance(object, classInfo)

        object: 要判断的实例对象
        classInfo: 期望的类型,可以是直接或间接类名、基本类型或者由它们组成的元组

    isinstance() 与 type() 区别:

        type() 不会认为子类是一种父类类型,不考虑继承关系。
        isinstance() 会认为子类是一种父类类型,考虑继承关系。

    注意:如果要判断两个类型是否相同推荐使用 isinstance()

    从示例简单可以看出isinstance()与type() 的一些区别,如果想知道子类与父类之间的继承关系还可以用issubclass() 或 object.__bases__


    metaclass

        metaclass 元类,可以控制类的属性和类实例的创建过程。如果希望创建某一批类全部具有某种特征,则可通过 metaclass 来实现。使用 metaclass 可以在创建类时动态修改类定义。

    对象、类、元类 关系图

    在Python 中,一切都可以是对象,整数、字符串、类实例、类本身也是对象,和其他对象一样,它是metaclass 的一个实例。

        从示例的结果可以看出,默认的metaclass 是type类型的,所以我们看到Person 的类型是type,type类型?从这里可以看出有点奇怪,从开始type函数的时候,有说明过type()是可以当做函数来使用的,返回的是一个对象的类型。目前看来就有点困惑了,其实在Python中type是一个极为特殊的类型,为了彻底理解metaclass,需要先理清楚type和object的关系。

    type与object 的关系

        在Python3中,object 是所有类的基类,内置的类、自定义的类都是直接或者间接的继承object类,去看源码,会发现type类也是继承object类,那么问题来了?

    1.首先 type 是一个metaclass ,而且是一个默认的metaclass,可以理解为type是object的类型,object又是type的一个实例。
    2.type 是object 的一个子类,继承object的所有属性和行为
    3.type还是一个callable对象,即实现了__call__方法,可以使用type()返回对象的类型

        type 和object的关系是不可分离的,type是object的子类,同时 object又是type的一个实例(type是object的类型),type的类型也是type,看到这里我也有点费劲。但是不管它,知道是怎么回事就行了。难受

    自我总结了一下:metaclass 是创建类的那个类。在python3中,我们自己定义的类,比如说Person,Animal类,它们默认的元类就是type。换句话说,Person类,Animal类也是对象,它们是type类的实例对象。因为:一切皆是对象。那么反过来可以说元类的实例就是类。

    1.类由type创建,创建类时,type的__init__方法自动执行,类() 执行type的 __call__方法(类的__new__方法,类的__init__方法)

    2.对象由类创建,创建对象时,类的__init__方法自动执行,对象()执行类的 __call__ 方法

    这么讲是不是就好理解多了?

    下面我们来自定义一个 metaclass,自定义的metaclass 必须继承 type,自定义的metaclass 通常以Metaclass或Meta作为后缀取名来区分。

    所有的累都继承自object,包括内置的类和用户自定义的类都是。一般来说,类class的类型为type(即一般的类的metaclass都是默认type,也就是type的一个实例),如果想改变类的metaclass,那么在定义类的时候,显式的指定它的metaclass即可。

        在自定义metaclass的注意点:

        1. object的__init__方法只有一个参数,单自定义metaclass的__init__有4个。
            def __init__(self): object 只有self参数
            def __init__(cls, what, bases=None, dict=None): 因为自定义的metaclass是继承type,所有必须要有4个参数。继承的super()
         2.对于普通的类,重写__call__ 方法说明这个对象是callable,但在metaclass中__call__ 还负责对象的创建

        下面结果代码示例看一下对象的创建过程

    示例代码 测试代码

    结合示例来分析一个实例对象的完整创建的过程:

    1.metaclass.__init: 首先进行初始化操作
    2.metaclass.__call__: 创建实例,在穿件的过程中会调用class 的 __new__/__init__方法
    3.class.__new__: 进行具体的实例化操作,并返回一个实例对象 at 0x000001851AC65808>
    4.class.__init__: 返回一个实例对象 at 0x000001851AC65808 进行初始化
    5. 返回一个用户真正需要的对象 object at 0x000001851AC65808>

     从以上示例结果和对结果的分析,可以看出metaclass是如何定义一个实例对象的,以及对象在生命周期完整创建过程。

    本篇学习笔记涉及的技术概念均来自《人人都懂设计模式》,有兴趣的同学可以去看看......

    相关文章

      网友评论

          本文标题:Python metaclass/type 原理详解

          本文链接:https://www.haomeiwen.com/subject/ezgyphtx.html