Python源码学习:内建类型简析并简析int对象

Python源码分析

本文环境python2.5系列
参考书籍<<Python源码剖析>>

上一篇文章中已经大致分析了下,Python的启动执行流程,现在我们分析一下Python的内建类型的基础知识。
在Python中,一切都是对象,整数,字符串,类型,函数等都是对象。在C语言层面的实现主要是通过一个PyObject结构体实现的。

分析

PyObject是描述的定长对象,如整型数字,PyVarObject描述变长对象,如字符串对象。
位于include/object.h中

typedef struct _object {
    PyObject_HEAD
} PyObject;

typedef struct {
    PyObject_VAR_HEAD
} PyVarObject;

继续查看PyObject_HEAD

#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; /* Number of items in variable part */

由此可以看见变长类型基本对象多了记录空间大小的一个标志位,最根本也是包含了PyObject_HEAD,这样PyObject就可以指向Python任意的对象。
我们继续查看ob_type类型;

typedef struct _typeobject {
    PyObject_VAR_HEAD
    const char *tp_name; /* For printing, in format "<module>.<name>" */
    Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */

    /* Methods to implement standard operations */

    destructor tp_dealloc;
    printfunc tp_print;
    getattrfunc tp_getattr;
    setattrfunc tp_setattr;
    cmpfunc tp_compare;
    reprfunc tp_repr;

    /* Method suites for standard classes */

    PyNumberMethods *tp_as_number;
    PySequenceMethods *tp_as_sequence;
    PyMappingMethods *tp_as_mapping;

    /* More standard operations (here for binary compatibility) */

    hashfunc tp_hash;
    ternaryfunc tp_call;
    reprfunc tp_str;
    getattrofunc tp_getattro;
    setattrofunc tp_setattro;

    /* Functions to access object as input/output buffer */
    PyBufferProcs *tp_as_buffer;

    /* Flags to define presence of optional/expanded features */
    long tp_flags;

    const char *tp_doc; /* Documentation string */

    /* Assigned meaning in release 2.0 */
    /* call function for all accessible objects */
    traverseproc tp_traverse;

    /* delete references to contained objects */
    inquiry tp_clear;

    /* Assigned meaning in release 2.1 */
    /* rich comparisons */
    richcmpfunc tp_richcompare;

    /* weak reference enabler */
    Py_ssize_t tp_weaklistoffset;

    /* Added in release 2.2 */
    /* Iterators */
    getiterfunc tp_iter;
    iternextfunc tp_iternext;

    /* Attribute descriptor and subclassing stuff */
    struct PyMethodDef *tp_methods;
    struct PyMemberDef *tp_members;
    struct PyGetSetDef *tp_getset;
    struct _typeobject *tp_base;
    PyObject *tp_dict;
    descrgetfunc tp_descr_get;
    descrsetfunc tp_descr_set;
    Py_ssize_t tp_dictoffset;
    initproc tp_init;
    allocfunc tp_alloc;
    newfunc tp_new;
    freefunc tp_free; /* Low-level free-memory routine */
    inquiry tp_is_gc; /* For PyObject_IS_GC */
    PyObject *tp_bases;
    PyObject *tp_mro; /* method resolution order */
    PyObject *tp_cache;
    PyObject *tp_subclasses;
    PyObject *tp_weaklist;
    destructor tp_del;

#ifdef COUNT_ALLOCS
    /* these must be last and never explicitly initialized */
    Py_ssize_t tp_allocs;
    Py_ssize_t tp_frees;
    Py_ssize_t tp_maxalloc;
    struct _typeobject *tp_prev;
    struct _typeobject *tp_next;
#endif
} PyTypeObject;

这个类型主要包含了类型名,创建类型对象分配的内存空间的大小,与该对象相关的操作信息,如果打印信息,哈希函数,获取该类型属性的方法等,该类型的相关信息,如该类型的基类信息,继承关系,子类信息等。
其中tp_as_number,tp_as_sequence,tp_as_mapping这三个属性就是对应于Python中比较典型的整型int,列表list,字典dict的类型对应的操作方法,如果是两个int相加就会调用tp_as_number中的nb_add方法来相加,如果是dict类型,通过key获取值,则调用tp_as_mapping中的mp_subscript方法,由此可看,Python中一个基本类型对应这些特性,在运行时可以根据需要往相应方法中填写方法就可以获取相应的特性,这也是Python动态的体现。
由该定义可知PyTypeObject也是一个对象,包含了PyObject_VAR_HEAD。
这也突出了就算是类型也是一个对象,该类型的类型就是PyType_Type,所有用户自定义的类都是通过type继承而来。

通过以上分析后,我们简析一下int类型的创建过程;
PyIntObject的定义如下

typedef struct {
    PyObject_HEAD
    long ob_ival;   // 这就是存放的整型的值
} PyIntObject;

其中生成的类型为

PyTypeObject PyInt_Type = {
    PyObject_HEAD_INIT(&PyType_Type)
    0,
    "int",
    sizeof(PyIntObject),
    0,
    (destructor)int_dealloc,        /* tp_dealloc */
    (printfunc)int_print,           /* tp_print */
    0,                  /* tp_getattr */
    0,                  /* tp_setattr */
    (cmpfunc)int_compare,           /* tp_compare */
    (reprfunc)int_repr,         /* tp_repr */
    &int_as_number,             /* tp_as_number */
    0,                  /* tp_as_sequence */
    0,                  /* tp_as_mapping */
    (hashfunc)int_hash,         /* tp_hash */
        0,                  /* tp_call */
        (reprfunc)int_repr,         /* tp_str */
    PyObject_GenericGetAttr,        /* tp_getattro */
    0,                  /* tp_setattro */
    0,                  /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
        Py_TPFLAGS_BASETYPE,        /* tp_flags */
    int_doc,                /* tp_doc */
    0,                  /* tp_traverse */
    0,                  /* tp_clear */
    0,                  /* tp_richcompare */
    0,                  /* tp_weaklistoffset */
    0,                  /* tp_iter */
    0,                  /* tp_iternext */
    int_methods,                /* tp_methods */
    0,                  /* tp_members */
    0,                  /* tp_getset */
    0,                  /* tp_base */
    0,                  /* tp_dict */
    0,                  /* tp_descr_get */
    0,                  /* tp_descr_set */
    0,                  /* tp_dictoffset */
    0,                  /* tp_init */
    0,                  /* tp_alloc */
    int_new,                /* tp_new */
    (freefunc)int_free,                 /* tp_free */
};

包括哈希函数,整数比较,整数显示等方法。
其中定义的整型对象的方法如下:

static PyNumberMethods int_as_number = {
    (binaryfunc)int_add,    /*nb_add*/
    (binaryfunc)int_sub,    /*nb_subtract*/
    (binaryfunc)int_mul,    /*nb_multiply*/
    (binaryfunc)int_classic_div, /*nb_divide*/
    (binaryfunc)int_mod,    /*nb_remainder*/
    (binaryfunc)int_divmod, /*nb_divmod*/
    (ternaryfunc)int_pow,   /*nb_power*/
    (unaryfunc)int_neg, /*nb_negative*/
    (unaryfunc)int_pos, /*nb_positive*/
    (unaryfunc)int_abs, /*nb_absolute*/
    (inquiry)int_nonzero,   /*nb_nonzero*/
    (unaryfunc)int_invert,  /*nb_invert*/
    (binaryfunc)int_lshift, /*nb_lshift*/
    (binaryfunc)int_rshift, /*nb_rshift*/
    (binaryfunc)int_and,    /*nb_and*/
    (binaryfunc)int_xor,    /*nb_xor*/
    (binaryfunc)int_or, /*nb_or*/
    int_coerce,     /*nb_coerce*/
    (unaryfunc)int_int, /*nb_int*/
    (unaryfunc)int_long,    /*nb_long*/
    (unaryfunc)int_float,   /*nb_float*/
    (unaryfunc)int_oct, /*nb_oct*/
    (unaryfunc)int_hex,     /*nb_hex*/
    0,          /*nb_inplace_add*/
    0,          /*nb_inplace_subtract*/
    0,          /*nb_inplace_multiply*/
    0,          /*nb_inplace_divide*/
    0,          /*nb_inplace_remainder*/
    0,          /*nb_inplace_power*/
    0,          /*nb_inplace_lshift*/
    0,          /*nb_inplace_rshift*/
    0,          /*nb_inplace_and*/
    0,          /*nb_inplace_xor*/
    0,          /*nb_inplace_or*/
    (binaryfunc)int_div,    /* nb_floor_divide */
    int_true_divide,    /* nb_true_divide */
    0,          /* nb_inplace_floor_divide */
    0,          /* nb_inplace_true_divide */
    (unaryfunc)int_int, /* nb_index */
};

有相加,相减,相除等Python支持的整型操作方法,由此看见当生成一个PyIntObject时,其中的ob_type为PyInt_Type,并且PyInt_Type的类型为PyType_Type,该为所有类型的类型。
当需要创建一个int对象时,调用PyInt_FromLong(long);

PyObject *
PyInt_FromLong(long ival)
{
    register PyIntObject *v;
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
    if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) {
        v = small_ints[ival + NSMALLNEGINTS];
        Py_INCREF(v);
#ifdef COUNT_ALLOCS
        if (ival >= 0)
            quick_int_allocs++;
        else
            quick_neg_int_allocs++;
#endif
        return (PyObject *) v;
    }
#endif
    if (free_list == NULL) {
        if ((free_list = fill_free_list()) == NULL)
            return NULL;
    }
    /* Inline PyObject_New */
    v = free_list;
    free_list = (PyIntObject *)v->ob_type;
    PyObject_INIT(v, &PyInt_Type);
    v->ob_ival = ival;
    return (PyObject *) v;
}

由于Python对于常用的整数进行了缓存所以会先检查是否是缓存的整型对象,如果不是则新建,我们继续查看PyObject_INIT函数

#define PyObject_INIT(op, typeobj) \
    ( (op)->ob_type = (typeobj), _Py_NewReference((PyObject *)(op)), (op) )

将ob_type的域的值设置成PyInt_Type,至此一个整型对象就生成了。
当两个整型对象相加时,

static PyObject *
int_add(PyIntObject *v, PyIntObject *w)
{
    register long a, b, x;
    CONVERT_TO_LONG(v, a);
    CONVERT_TO_LONG(w, b);
    x = a + b;
    if ((x^a) >= 0 || (x^b) >= 0)
        return PyInt_FromLong(x);
    return PyLong_Type.tp_as_number->nb_add((PyObject *)v, (PyObject *)w);
}

先将整型数字转换成long类型,然后相加,如果相加之后的结果没有溢出则,调用nb_add方法相加两个值,并将结果生成一个长整型对象返回。
至此,大致分析了一下Python中的基础类型的构成,并简析了下Python中的整型对象的类型与新建,如需要详细内容可查看源码。

猜你喜欢

转载自blog.csdn.net/qq_33339479/article/details/79684237