2. Python3源码—浮点对象

发布时间:2019-10-15 09:04:54编辑:auto阅读(1922)

    2.1. 浮点对象

    浮点对象是“定长对象”。

    2.1.1. Python中的创建

    Python中浮点对象创建最重要的方法为PyFloat_FromDouble,如下Python语句最终会调用到PyFloat_FromDouble:

    a = 1.23
    b = float(1.234)

    2.1.2. PyFloat_FromDouble的C调用栈

    词法解析,最终调到PyFloat_FromDouble,调用顺序如下:

    // ast.c
    ast_for_expr
    =>ast_for_power
    =>ast_for_atom_expr
    =>ast_for_atom (case NUMBER)
    =>parsenumber
    =>parsenumber_raw
    
    // floatobject.c
    => PyFloat_FromDouble

    2.1.3. PyFloat_FromDouble的C源码

    // floatobject.c
    PyObject *
    PyFloat_FromDouble(double fval)
    {
        PyFloatObject *op = free_list;
        if (op != NULL) {
            free_list = (PyFloatObject *) Py_TYPE(op);
            numfree--;
        } else {
            op = (PyFloatObject*) PyObject_MALLOC(sizeof(PyFloatObject));
            if (!op)
                return PyErr_NoMemory();
        }
        /* Inline PyObject_New */
        (void)PyObject_INIT(op, &PyFloat_Type);
        op->ob_fval = fval;
        return (PyObject *) op;
    }

    可以看到:

    • 浮点对象的C数据结构,所以Python中的浮点对象,实际上是C中的double。
    // floatobject.h
    typedef struct {
        PyObject_HEAD
        double ob_fval;
    } PyFloatObject;
    • 采用浮点对象缓冲池
    // floatobject.c
    #ifndef PyFloat_MAXFREELIST
    #define PyFloat_MAXFREELIST    100
    #endif
    static int numfree = 0;
    static PyFloatObject *free_list = NULL;
    
    static void
    float_dealloc(PyFloatObject *op)
    {
        if (PyFloat_CheckExact(op)) {
            if (numfree >= PyFloat_MAXFREELIST)  {
                PyObject_FREE(op);
                return;
            }
            numfree++;
            Py_TYPE(op) = (struct _typeobject *)free_list;
            free_list = op;
        }
        else
            Py_TYPE(op)->tp_free((PyObject *)op);
    }
    
    PyObject *
    PyFloat_FromDouble(double fval)
    {
        PyFloatObject *op = free_list;
        if (op != NULL) {
            free_list = (PyFloatObject *) Py_TYPE(op);
            numfree--;
        } else {
            op = (PyFloatObject*) PyObject_MALLOC(sizeof(PyFloatObject));
            if (!op)
                return PyErr_NoMemory();
        }
        /* Inline PyObject_New */
        (void)PyObject_INIT(op, &PyFloat_Type);
        op->ob_fval = fval;
        return (PyObject *) op;
    }

    float_dealloc和PyFloat_FromDouble方法针对free_list和numfree的操作构成了Python的浮点对象缓冲池技术。采用链表,值得注意的是Py_TYPE(op),在此处被当做next指针。缓冲池大小有上限,Python3中为100。

    • PyObject_INIT

      因为是定长对象,所以调用PyObject_INIT方法,与PyObject_INIT_VAR方法相比,只是少调用Py_SIZE(op) =(size)

    2.2. 浮点对象的特性

    2.2.1. 数值计算

    // floatobject.c
    &float_as_number,                           /* tp_as_number */

    浮点对象的数值计算由float_as_number定义:

    // floatobject.c
    static PyNumberMethods float_as_number = {
        float_add,          /* nb_add */
        float_sub,          /* nb_subtract */
        float_mul,          /* nb_multiply */
        float_rem,          /* nb_remainder */
        float_divmod,       /* nb_divmod */
        float_pow,          /* nb_power */
        (unaryfunc)float_neg, /* nb_negative */
        float_float,        /* nb_positive */
        (unaryfunc)float_abs, /* nb_absolute */
        (inquiry)float_bool, /* nb_bool */
        0,                  /* nb_invert */
        0,                  /* nb_lshift */
        0,                  /* nb_rshift */
        0,                  /* nb_and */
        0,                  /* nb_xor */
        0,                  /* nb_or */
        float___trunc___impl, /* nb_int */
        0,                  /* nb_reserved */
        float_float,        /* nb_float */
        0,                  /* nb_inplace_add */
        0,                  /* nb_inplace_subtract */
        0,                  /* nb_inplace_multiply */
        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 */
        float_floor_div,    /* nb_floor_divide */
        float_div,          /* nb_true_divide */
        0,                  /* nb_inplace_floor_divide */
        0,                  /* nb_inplace_true_divide */
    };

    2.2.2. to string

    // floatobject.c
    (reprfunc)float_repr,                       /* tp_repr */
    (reprfunc)float_repr,                       /* tp_str */

    2.2.3. hash

    // floatobject.c
    (hashfunc)float_hash,                       /* tp_hash */

    2.2.4. 比较

    // floatobject.c
    float_richcompare,                        /* tp_richcompare */

    2.2.5. 内置方法

    // floatobject.c
    float_methods,                              /* tp_methods */

    2.2.6. 内置属性

    // floatobject.c
    float_getset,                                /* tp_getset */

    2.3 参考

    • Python源码剖析

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

关键字