对PyObject的一点理解

很久之前看过一篇有关Python的list的博客,里面提到,Python中list的数据结构是这样的:

我很不理解的是,list完全可以存储×ob_item就可以了啊,为什么要存放××ob_item呢?

只要list的每一个元素存放的是指向PyObject的指针,就已经可以实现增删改查了,维护一些指向PyObject的指针就可以了,而且指针只有一层,还比“指向指针的指针”更快一些。百思不得其解,去stackoverflow上面提问,有个人回答,这样的话,如果要修改list的值,只要将指针指向另一个“指向PyObject的指针”就可以了。但是我觉得,即使是存一层指针,repoint也不是很麻烦。

后来自己就想了很长时间,跟朋友吃饭讨论过,跟张哥也讨论过。

昨天晚上,我感觉自己有点理解了。

首先,PyObject肯定是不能拿来用的,因为这就是文件系统的blob一样,我们用的是指向它的node,看他的文件块没有意义。所以一般来说,我们用的是×PyObject来操作Python对象。换句话说,我们基本上不会去直接搞PyObject,×PyObject一般是我们能获得PyObject的唯一方式。那么如果在list里面存放一层指针,即×PyObject的话,就差不多是复制这个对象进去了(虽然存放的也是指针)。参考下图:

PyObject

这个时候,如果从list的索引改了PyObject,那么×PyObject也会受影响,是指向了同一个对象(这个地方和××PyObject)是一样的。但是考虑这样一种情况:

假如是我想象的list存放的是×PyObject的话,我们将tom添加到list之后,重新给tom赋值了一个对象,也就是说,tom指向了另一个对象。但是li中的tom是直接指向一个对象的。也就是说,tom的repoint就和li中的tom关联不到了。

可能说的有点绕,和指针相关就比较麻烦,简单来说,就是:如果list存放的是×PyObject,那么变量重新指向别的对象的话,list存放的变量还是指向原来的对象,我们无法通过引用给list中的元素重新指向了(只能通过list的索引重新指向)。这就点像软链接和硬链接的区别。

但是如果存放的是××PyObject,那么引用(×PyObject)指向的什么,数组里面就存放的什么:

PyObject -pointer

另外,如果list存放×PyObject,那么list的元素改变之后,旧元素很可能没有指针指向它了,很可能被作为垃圾回收。

以上,是我这几天的理解,没有经过验证,很可能都是错误的。



Leave a comment

您的电子邮箱地址不会被公开。 必填项已用 * 标注