Python中的元类(metaclass)和基类(baseclass)

CPython中的类型体系

  在Python中,一切都是对象。一个整数是一个对象,一个类型,比如整数类型也是一个对象;一个类是对象,一个对象也是对象。对象是面向对象编程里面的概念。而CPython中用结构体实现了这一概念。
  假如我们定义一个整型,我们做如下实验:

>>> i=10
>>> type(i)
<class 'int'>
>>> type(int)
<class 'type'>
>>> isinstance(i,int)
True
>>> isinstance(int,type)
True
>>> isinstance(type,type)
True

  变量i的类型为int,而类型int的类型为type,类型type的类型为其本身type。使用函数isinstance(),我们可以看到:iint的一个实例,inttype的一个实例,typetype自己本身的一个实例。看来搞清楚类型表示以及这个type是什么,很有必要。

  对于类型,CPython中有一个重要的结构体(PyTypeObject),它可以用来表示一个整数类型,一个字符串类型,一个声明的类。在PyTypeObject中有两个字段非常值得我们学习。

  1. ob_type说明了实例关系(instance()函数)
  2. tp_base说明了类的继承关系(issubclass()函数)
typedef struct _typeobject {
    Py_ssize_t ob_refcnt;
    struct _typeobject *ob_type;
    //......
    struct _typeobject *tp_base;
    //......
} PyTypeObject;

元类和基类

在面向对象编程中,元类的实例化对象是类。

  Python中有两个必须理解的对象(type、object)。type被看做是默认元类,object被看做是默认基类。不过面向对象只是语义层次的概念。如果真正解释type和object,我想它们只是两个结构体而已。所以,不存在鸡生蛋蛋生鸡的讨论。
  type和object同是PyTypeObject类型的结构体。type叫PyType_Type;object叫PyBaseObject_Type。

  所有的PyTypeObject类型的结构体中的ob_type都指向了PyType_Type,而PyType_Type中的ob_type指向了自身。在Python语境中的实例,便是由ob_type的指向来决定的。所以,既然所有PyTypeObject都指向PyType_Type,那所有的PyTypeObject都是实例化的PyType_Type。在Python中,PyType_Type即是type,type便是元类(metaclass)。
  而tp_base的指向表明了继承关系,未指明继承关系的类都默认是PyBaseObject_Type的子类。所以,PyBaseObject_Type是继承关系的最上层,即Python语境中的object,object便是基类。

  既然所有的PyTypeObject都是实例化的PyType_Type,那PyBaseObject_Type应该也是PyType_Type的一个实例;即Python语境中object是type的一个实例;
  既然所有的PyBaseObject_Type是所有类的基类,那PyType_Type应该也是PyBaseObject_Type的一个子类;即Python语境中type是object的子类。