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();
}
(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();
}
(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,
浮点对象的数值计算由float_as_number定义:
// floatobject.c
static PyNumberMethods float_as_number = {
float_add,
float_sub,
float_mul,
float_rem,
float_divmod,
float_pow,
(unaryfunc)float_neg,
float_float,
(unaryfunc)float_abs,
(inquiry)float_bool,
0,
0,
0,
0,
0,
0,
float___trunc___impl,
0,
float_float,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
float_floor_div,
float_div,
0,
0,
};
2.2.2. to string
// floatobject.c
(reprfunc)float_repr,
(reprfunc)float_repr,
2.2.3. hash
// floatobject.c
(hashfunc)float_hash,
2.2.4. 比较
// floatobject.c
float_richcompare,
2.2.5. 内置方法
// floatobject.c
float_methods,
2.2.6. 内置属性
// floatobject.c
float_getset,
2.3 参考
- Python源码剖析
本文作者:whj0709
阅读原文
本文为云栖社区原创内容,未经允许不得转载。