欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

《python源码剖析》读书笔记二

程序员文章站 2022-07-14 16:21:06
...

python对象

在很多所谓的技术群中,经常会遇到不少讨论语言的对话。他们大谈语言的特性、语言的性能。这真是太naive了,就像某大神所说的——人们经常觉得python的代码运行效率低,其实只是你写的代码效率低而已。
对于计算机而言,它根本不知道我们所讨论的python、ruby、golang、nodejs有什么区别。因为在底层,这些语言的具体实现都是字节。
对于人而言,是很好理解的python对象,其概念就是:数据以及基于这些数据操作的集合。而对于计算机,py对象就是为C中的结构体在堆(heap)上申请的一块内存。一般而言,对象是不能被静态初始化,也不能在栈(stack)空间上生存的。而类型对象是可以的。这样,容纳可变长度数据的对象只能在对象内部维护一片指针区域。通过这种机制,来简化维护指针的工作。
对于python对象,PyObject则是基石。

[object.h]
typedef struct _object {
    pyObject_HEAD #宏
} PyObject;

typedef struct _object{
    int ob_refcnt;
    struct _typeobject *ob_type;
} PyObject;

这就是所有python对象都拥有的头信息定义。其中ob_refcnt用于python的内存管理,是python GC的重要影响因素。它实现了python基于计数的垃圾回收机制。这里也让我想起之前看过的一篇文章,讲的导致python程序内存泄漏的一种原因:
比如在命名空间(Naming Space,NS)中创建对象A,然后创建对象B。这样两个对象的引用计数都会增加1,那么假设对象A和B内部都有方法,涉及到彼此。那么两者的引用数又会增加1。然后触发对象的del()方法,在命名空间删除对象。这样其他代码就无法再访问这两个对象,然而两者的引用计数并未减到0,所以两者并不会从内存中被销毁。
python的对象链表由3层,如果多次GC后,这些残留的内容便会存留在最老生代的链表上。由此导致内存泄漏。
而下面的内容,表示ob_type是_typeobject的指针,用来指定对象类型的类型对象。
以上两部分的内容是所有py对象,无论内建还是自定义都拥有的。然后用整数int对象来说明。

[intobject.h]
typedef struct {
    PyObject_HEAD;
    long ob_ival;
} PyIntObject;

ob_ival 这个long型保存的就是int对象的数值

定长对象和变长对象