四时宝库

程序员的知识宝库

Python源码剖析(一)——对象的核心基石PyObject

众所周知,Python是一门动态语言,OOP语言(面向对象),也是由C语言写成的。不过C语言是面向过程的,所以我一直都挺好奇Python的面向对象机制是怎么实现的。

面向对象机制

对象对于计算机来说,就是一片被分配的内存空间,这片空间可以是离散的,也可以是连续的,主要是我们一旦将这片空间称作对象,那么这片空间在使用过程中可以作为一个整体来考虑。

在Python中,对象就是为C结构体中在堆上申请的一块内存,一般来说,对象是不能初始化的,也不能在栈空间上生存,唯一例外的是类型对象(Type Object),这比较容易理解,类型对象是Python固定好的最原始的类,这些内建的Type Object都是被静态(static)初始化的。

当然Python中一个对象被创建内存的大小就是不变的了,那么为什么list,dict等对象可以实现可变长度呢?这要归功于Python约定俗成的规则——在对象中维护一个指向一块可变大小的内存区域指针。

这样做有什么好处?简单来说就是容易维护。举个简单的栗子,假设Python的list、dict的实例对象的内存挨在一起,那么当list变长时,就会覆盖了dict的内存。如果对象中有个可变大小的指针,那么将多出来的内存移动到可变区域即可,维护起来十分方便。

PyObject

在Python中所有东西都是对象,这很容易理解,int、str、list都是一个class,即对象。而且所有对象都拥有一些相同的内容,这是因为它们继承了Object,在C语言中即是PyObject,PyObject是整个Python对象机制的核心。

从代码中可以看到,整个核心都在PyOject_HEAD这个宏中。在实际发布的Python中,PyObject的定义非常简单:

  • 引用计数;
  • 类型信息。

在PyObject的定义中,整形变量ob_refcnt与Python的内存管理机制有关,实现了基于引用计数的垃圾收集机制。

该机制可简单理解如下:当对象A有一个新的PyObject *引用该对象时A的引用计数增加,当PyObject *被删除时,A的引用计数减少。当A的引用计数为0时,A就可以从堆上被删除,释放出内存供别的对象用。

而ob_type是一个指向_typeobject结构体的指针,这个结构体是用来指定一个对象类型的类型对象(Type Object)。

所以简而言之,所有的Python对象都必须有PyObject中的内容,这些内容将出现在每个Python对象所占有的内存的最开始的字节中。

下一次会继续讲PyObject的更多细节,欢迎关注阅读。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接