zoukankan      html  css  js  c++  java
  • Python源码分析:PyObject对象的起源与多态的实现

    在python中一切皆是对象,那么这种机制是如何实现的呢?下面就让我们从python的老巢“源码”来看看这个神秘的机制。

    typedef struct _object {

    PyObject_HEAD

     } PyObject;

     

    typedef struct {

    PyObject_VAR_HEAD

    } PyVarObject;

     

    看到上面这两个结构体了吗?它们就是万源之源,所有python对象的祖先,为什么有两个祖先呢?这就要从现实时间的数据对象谈起,我们有些数据,像数字、固定矩阵这类数据其元素个数是固定不变的,而像字符串、集合、字典这类数据其元素个数是会上下浮动的。这样python的发明者在设计python时就为这两类数据创造了两个祖先(像人有男人与女人一样,好像不太确切,但本质就是有两个祖先了):定长数据类型与变长数据类型。

    这两个结构体里面的两个变量,其实都是些宏。从源中我们可以找到这些宏的展开:

    #define PyObject_HEAD

    _PyObject_HEAD_EXTRA

    Py_ssize_t ob_refcnt;

     

    struct _typeobject *ob_type;

    #define PyObject_VAR_HEAD

    PyObject_HEAD

    Py_ssize_t ob_size;

    看得出来,类型多了的这个ob_size就说明了它的变长特性(元素的个数)。

    下面我们来仔细看看PyObject_HEAD这个宏的内容:

    _PyObject_HEAD_EXTRA:这个宏展开时要么是双向链表的前后指针要么是空,是在跟踪所有对象时使用:想像一下,一个双向链表把python所有的对象串联起来的场景,好宏大呀!

    ob_refcnt:这个属性记录该对象被他人引用的次数(后面发现,这个东西是用来进行内存管理的:引用计数式的垃圾回收机制)

    ob_type:这个玩意是个重头戏,它实现了python的多态(何谓多态:对于不同的类型的对象,相同名称的方法其表现行为不同),何以见得呢?下面就让我们重点分析下这个ob_type,首先看看ob_type的原型是什么:

    typedef struct _typeobject {

    PyObject_VAR_HEAD

    const char *tp_name;

    Py_ssize_t tp_basicsize, tp_itemsize;

    printfunc tp_print;

    。。。

     

    PyNumberMethods *tp_as_number;

    PySequenceMethods *tp_as_sequence;

    PyMappingMethods *tp_as_mapping;

    。。。

    } PyTypeObject;

    这个结构体在源代码中整整占了84行,天呢!它是个什么,这么多内容。我们重点看几个字段:

    PyObject_VAR_HEAD

    :嗯,这不是变长数据类型它老祖先里的头‘骨’吗?怎么这里还有呢?没错,你猜对了,我们指明某个对象类型的对象原型 PyTypeObject也是一个对象。至于为什么是变长类型的对象祖先的头’骨‘,还没搞清楚^0^。

    tp_print:多态的内部原理开始显露了吧!就是通过这个type对象来为具体不同的对象提供不同的方法实现,尽量方法名字都一样。

    PyNumberMethods,PySequenceMethods,PyMappingMethods:其实和上面这个tp_print一样,只不它们是个函数族(由函数集构成),类数字操作(比如支持+-×/)、类序列操作(比如[n:m]切片操作)、字典操作(比如dict[key]操作)。

    下面就int类型对象对上面这些原理进行验证:

    typedef struct {

    PyObject_HEAD

    long ob_ival;

    } PyIntObject;

    这就是我们的int类型对象,其头部呢?在python源中可以看出,用一系列宏来实现头部的初始化:

    #define PyObject_HEAD_INIT(type)

    _PyObject_EXTRA_INIT

    1, type,

    这里的type,从源码中看出,有一个PyType_Type类型,它就是那个描述类型的类型的对象。有点绕了,但是仔细理解下来,也没什么,无外乎:一个int数据,有一个专门描述int类型数据的类型对象,但是不光有int类型的类型对象还有string类型的类型对象。那么就需要有一个要对象来描述这些类型对象,这就是PyType_Type,也就是它可以测试一个对象是不是类型对象。

  • 相关阅读:
    NX二次开发-UFUN获取当前主要版本的版本号
    NX二次开发-UFUN创建图纸注释uc5540
    VC++ADO/COM,put_LeftMargin设置纸张上下左右边距的大小
    VC++ADO/COM,put_Orientation组件设置纸张方向0默认1纵向2横向
    常用的数据拼接方法(不断更新中)
    去重对象数组
    将对象数组中指定键值赋给另一个数组并对更改对象数组中的key
    CSS3动态计算公式——calc()的坑
    @PostConstruct注解
    java操作Redis缓存设置过期时间
  • 原文地址:https://www.cnblogs.com/muyiblog/p/7675669.html
Copyright © 2011-2022 走看看