文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

1. Python3源码—内建对象

2023-01-31 08:21

关注

1.1. Python内的对象

Python中的类和实例都是通过Python内的对象来实现的。Python中已经预先定义了一些类型对象。这些内建类型对象通过实例化,可以创建内建类型对象的实例对象。

在Python中,对象就是为C中的结构体在堆上申请的一块内存,一般来说,对象是不能被静态初始化的,并且也不能在栈空间上生存。唯一的例外就是类型对象,Python中所有的内建的类型对象都是被静态初始化的。

在Python中,一个对象一旦被创建,它在内存中的大小就是不变的了。这就意味着那些需要容纳可变长度数据的对象只能在对象内维护一个指向一块可变大小的内存区域的指针。

1.2. PyObject

PyObject是整个Python对象机制的核心,定义如下:

// object.h
typedef struct _object {
    _PyObject_HEAD_EXTRA
    Py_ssize_t ob_refcnt;
    struct _typeobject *ob_type;
} PyObject;

其中_PyObject_HEAD_EXTRA定义如下:

// object.h
#ifdef Py_TRACE_REFS

#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

可以看到release编译时不会定义Py_TRACE_REFS。

PyObject类中ob_refcnt与内存引用计数相关,ob_type用来指定一个对象类型的类型对象。在Python中,对象机制的核心一个是引用计数,一个就是类型信息。

每一个Python对象除了必须有这个PyObject内容外,还应该占有一些额外的内存,放置些其他的东西。比如float对象除了PyObject,还有一个额外的double变量,如下定义:

// object.h

#define PyObject_HEAD PyObject ob_base;

1.3. PyVarObject

把浮点对象这样不包含可变长度数据的对象称为“定长对象”,而字符串对象这样包含可变长度数据的对象称为“变长对象”,它们的区别在于定长对象的不同对象占用的内存大小是一样的,而变长对象的不同对象占用的内存可能是不一样的。

表示变长对象的结构体PyVarObject定义如下:

// object.h
typedef struct {
    PyObject ob_base;
    Py_ssize_t ob_size; 
} PyVarObject;

每一个可变Python对象除了有PyVarObject内容外,还占有一些额外的内存,放置些其他的东西。比如list对象为变长对象,它的结构体如下:

// listobject.h
typedef struct {
    PyObject_VAR_HEAD
    PyObject **ob_item;
    Py_ssize_t allocated;
} PyListObject;

其中PyObject_VAR_HEAD定义了PyVarObject类型对象,如下:

// object.h

#define PyObject_VAR_HEAD     PyVarObject ob_base;

1.4. PyTypeObject

对象对应的类型对象定义如下:

// object.h
typedef struct _typeobject {
    PyObject_VAR_HEAD
    const char *tp_name; 

    Py_ssize_t tp_basicsize, tp_itemsize;

    
    destructor tp_dealloc;
    printfunc tp_print;
    
       // ...
} PyTypeObject;

定义中包含了许多信息,主要分为4类:

  • 类型名,tp_name,主要是Python内部以及调试的时候使用;
  • 创建该类型对象时分配内存空间大小的信息,即tp_basicsize和tp_itemsize;
  • 与该类型对象相关联的操作信息,诸如tp_print这样的函数;
  • 类型的类型信息;

在PyTypeObject中定义了大量的函数指针,这些函数指针最终都会指向某个函数,或者指向NULL,可以视为类型对象中所定义的操作。在这些操作信息中,有三组非常重要的操作族:tp_as_number,tp_as_sequence和tp_as_mapping,分别指向PyNumberMethods,PySequenceMethods和PyMappingMethods函数族。PyNumberMethods、PySequenceMethods、PyMappingMethods分别定义了作为一个数值对象、序列对象和关联对象应该支持的操作。

类型对象的类型是PyType_Type:

PyTypeObject PyType_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "type",                            
    sizeof(PyHeapTypeObject),          
    sizeof(PyMemberDef),               
    (destructor)type_dealloc,          
    0,                                 
    0,                                 
    0,                                 
    0,                                 
    (reprfunc)type_repr,               
    0,                                 
    0,                                 
    0,                                 
    0,                                 
    (ternaryfunc)type_call,            
    0,                                 
    (getattrofunc)type_getattro,       
    (setattrofunc)type_setattro,       
    0,                                 
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
        Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TYPE_SUBCLASS,                                                   
    type_doc,                          
    (traverseproc)type_traverse,       
    (inquiry)type_clear,               
    0,                                 
    offsetof(PyTypeObject, tp_weaklist),  
    0,                                  
    0,                                  
    type_methods,                       
    type_members,                       
    type_getsets,                       
    0,                                  
    0,                                  
    0,                                  
    0,                                  
    offsetof(PyTypeObject, tp_dict),    
    type_init,                          
    0,                                  
    type_new,                           
    PyObject_GC_Del,                    
    (inquiry)type_is_gc,                
};

1.5. Python对外提供的C API

Python的C API分为两类,一类称为范性的API(AOL,Abstract Object Layer),这类API都具有诸如PyObject_*的形式,可以应用在任何Python对象上;另一类是与类型相关的API(COL,Concrete Object Layer),这类API通常只能作用在某一种类型的对象上,对于每一种内建对象,Python都提供了这样的一组API。

1.6 参考

  • Python源码剖析

本文作者:whj0709
阅读原文
本文为云栖社区原创内容,未经允许不得转载。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯