143716b5a212e73648af79363e63ea55
Python 对象与类

Python 对象与类

之前一直想思考设计一门编程语言,奈何自身的技术实力不到家,因此最近阅读了一些语言的源码设计。在阅读了一些语言的代码实现后,我决定先从模仿开发一款类Python的语言开始做一门自己的编程语言。

因此,我想专门写个系列,一方面记录我阅读Python这门语言的一些收获,来帮助大家对设计一套完备的工业级编程语言打下一定的基础。

对象与类

谈到现代化的高级编程语言,面向对象的编程能力不可缺少的能力,首当其冲的就是对象和类的概念设计。在Python中,所有的东西都是对象,并且所有对象的都具有相同的头部偏移(相对对象基地址的)的内容。

Python 2.7的源码我们可以看到对象的(简化版)结构定义:

typedef struct _object {
    PyObject_HEAD
} PyObject;

PyObject_HEAD则是一个快速的宏定义,用于包装引用计数以及对象类型。

#define PyObject_HEAD                   \
    Py_ssize_t ob_refcnt;               \
    struct _typeobject *ob_type;

这里我们暂时不去探究什么是类型对象,引用计数的道理比较清晰,相信写过Objective—C之类语言的同学对这个都比较明确。

  1. 这里有一点需要注意,在Python中,当对象的引用计数减为0的时候,不一定真的就会将对象释放,因为Python对对象做了很多诸如内存池的优化。

  2. 万物皆对象,在Python不存在基本数据类型类似intdouble(注意和Swift之类的语言进行区分)

好了,谈完了基本概念,我们来看看Python是如何设计面向对象中这个结构的。

首先我们回忆下我们在C++中定义一个类,大多数都是如下形式:

// 1.类名             2. 基类
class MyClass:public BaseClass {
    MyClass();  // 构造函数
    ~MyClass(); // 析构函数
};

从中我们不难归纳出,基本信息中我们至少需要如下东西:

  • 类名
  • 基类的继承关系链(能够通过这条链向上溯源)
  • 构造函数、析构函数等等。
  • 类型内存大小等等。

这些东西都是类型公用的,我们当然可以直接将这些对象都一股脑塞入PyObject对象中,但是这样就造成信息储存的冗余。所以,在Python中单独设计了一套数据结构PyTypeObject的概念,用于储存这些对象共用的信息,如下:

typedef struct _typeobject {
    PyObject_VAR_HEAD
    const char *tp_name; /* For printing, in format "<module>.<name>" */
    Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */

    /* Methods to implement standard operations */

    destructor tp_dealloc;
    printfunc tp_print;

    hashfunc tp_hash;

    /* Type attribute cache version tag. Added in version 2.6 */
    unsigned int tp_version_tag;

} PyTypeObject;

首先,再次强调下万物皆对象,因此PyTypeObject也具有相同的类型头部PyObject_VAR_HEAD,只不过这里的头部是针对非定长对象而设计,文末我们会专门讲解下区别。

好,基于此,如果我们构造了一个整数对象10(先假设此时存在类Int),代码Int(10)背后的结构如下图所示:

top Created with Sketch.