Python源码解读之二 万物皆对象(下)

本文深入探讨Python对象的实现,重点解析PyObject和PyVarObject的结构,包括引用计数、类型指针,以及如何实现变长对象。通过分析,揭示Python内存管理和类型对象的底层原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

初探PyObject

首先我们再次来回顾一下,在上一篇提到过,“类”和“对象”这两个概念在Python中都是用对象实现的。“类"是一种对象,称为"类型对象”,“类"实例化得到的也是"对象”,称为"实例对象"。

实现对象机制的基石–PyObject

Python中的任何对象在C中都对应一个结构体实例,在Python中创建一个对象,等价于在C中创建一个结构体实例。所以Python中的对象本质上就是C中malloc函数为结构体实例在堆区申请的一块内存。

/* Nothing is actually declared to be a PyObject, but every pointer to
 * a Python object can be cast to a PyObject*.  This is inheritance built
 * by hand.  Similarly every pointer to a variable-size Python object can,
 * in addition, be cast to PyVarObject*.
 */
typedef struct _object {
   
    _PyObject_HEAD_EXTRA        // 双向链表 垃圾回收 需要用到
    Py_ssize_t ob_refcnt;       // 引用计数
    PyTypeObject *ob_type;      // 指向类型对象的指针,决定了对象的类型
} PyObject;

_PyObject_HEAD_EXTRA是一个宏,展开后代码如下:

/* PyTypeObject structure is defined in cpython/object.h.
   In Py_LIMITED_API, PyTypeObject is an opaque structure. */
typedef struct _typeobject PyTypeObject;

#ifdef Py_TRACE_REFS
/* Define pointers to support a doubly-linked list of all live heap objects. */
#define _PyObject_HEAD_EXTRA            \
    struct _object *_ob_next;           \
    struct _object *_ob_prev;

#define _PyObject_EXTRA_INIT 0, 0,

#else
#  define _PyObject_HEAD_EXTRA
#  define _PyObject_EXTRA_INIT
#endif

_PyObject_HEAD_EXTRA:这个宏是一个双向链表,Python会将程序中创建的所有对象都放入到这个双向链表中,用于跟踪所有活跃的堆对像。不过这个宏只有在debug模式下生效。

PS:带EXTRA 字样的宏 只有在debug模式下才存在

重点要关注的是另外两个变量,ob_refcnt和*ob_type。

ob_refcnt:引用计数

在PyObject的定义中,整型变量ob_refcnt与Python的内存管理机制有关,它实现了基于引用计数的垃圾收集机制。对于某一个对象A,当有一个新的PyObject*引用该对象时,A的引用计数增加。

例如:

  • 对象创建 a = 123
  • 变量传递使得对象被新的变量引用a = b
  • 引用该对象的某个变量作为参数传到一个函数或者类中func(a)
  • 引用该对象的某个变量作为元组、列表、集合等容器的一个元素list = [a]

当这个PyObject*被删除时,A的引用计数减少,减少到0的时候,A就可以从堆上被删除,以释放出内存供别的对象使用。

例如:

  • 引用该对象的变量被显示的销毁:del a
  • 对象的引用指向了别的对象:a = "测试1" a = "测试2"
  • 引用该对象的变量离开了它的作用域,比如函数的局部变量在函数执行完毕的时候会被销毁
  • 引用该对象的变量所在的容器被销毁,或者被从容器里面删除

ob_type: 类型指针

所有的对象都是有类型的,类型对象描述实例对象的数据和行为,ob_type就是一个指向_typeobject结构体的指针,_

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值