# float
# 内部结构
# PyFloatObject
typedef struct {
PyObject_HEAD
double ob_fval;
} PyFloatObject;
# PyFloat_Type
PyFloat_Type 中保存了很多关于浮点对象的 元信息 ,关键字段包括:
- tp_name 字段保存类型名称,常量 float ;
- tp_dealloc 、 tp_init 、 tp_alloc 和 tp_new 字段是对象创建销毁相关函数;
- tp_repr 字段是生成语法字符串表示形式的函数;
- tp_str 字段是生成普通字符串表示形式的函数;
- tp_as_number 字段是数值操作集;
- tp_hash 字段是哈希值生成函数;
PyTypeObject PyFloat_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"float",
sizeof(PyFloatObject),
0,
(destructor)float_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
(reprfunc)float_repr, /* tp_repr */
&float_as_number, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)float_hash, /* tp_hash */
0, /* tp_call */
(reprfunc)float_repr, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
float_new__doc__, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
float_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
float_methods, /* tp_methods */
0, /* tp_members */
float_getset, /* 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 */
float_new, /* tp_new */
};
# 对象创建
# 对象创建API
除了通用的创建对象的流程,Python为内置对象实现了对象创建API,简化了调用:
PyObject * PyFloat_FromDouble(double fval);从浮点数创建浮点对象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; }
PyObject * PyFloat_FromString(PyObject *v);从字符串创建浮点对象
# 对象销毁
当对象不再需要时, Python 通过 Py_DECREF 或者 Py_XDECREF 宏减少引用计数
当引用计数降为 0 时, Python 通过 _Py_Dealloc 宏回收对象
- 实际调用的类型的tp_dealloc函数指针指向的函数
# 空闲对象缓存池
例如浮点运算备受设计到大量临时对象的创建以及销毁,这则意味着大量内存分配回收操作
因此Python在浮点对象销毁后,并不马上回收内存,而是将其加入一个空闲链表,后续需要创建浮点对象时,先到空闲链表中取,省去分配内存的开销。
if (numfree >= PyFloat_MAXFREELIST) { PyObject_FREE(op); return; } numfree++; Py_TYPE(op) = (struct _typeobject *)free_list; free_list = op;空闲链表定义在
Objects/floatobject.c中#ifndef PyFloat_MAXFREELIST #define PyFloat_MAXFREELIST 100 // 最大长度 #endif static int numfree = 0; // 当前长度 static PyFloatObject *free_list = NULL; // 链表头部为了保持简洁,Python 把 ob_type 字段当作 next 指针来用,将空闲对象串成链表
# 对象的行为
PyFloat_Type 中定义了很多函数指针,包括 tp_repr 、 tp_str 、 tp_hash 等,这些函数指针将一起决定 float 对象的行为。
例如tp_hash 函数决定浮点哈希值的计算,tp_hash 函数指针指向 float_hash 函数,实现了针对浮点对象的哈希值算法:
static Py_hash_t float_hash(PyFloatObject *v) { return _Py_HashDouble(v->ob_fval); }