chunjiekid 2019-06-27
浮点对象是“定长对象”。
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; }
可以看到:
// 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_VAR方法相比,只是少调用Py_SIZE(op) =(size)
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 */
本文作者:whj0709
阅读原文
本文为云栖社区原创内容,未经允许不得转载。