马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
Python版本号 3.8.6
在阅读Python源码的时候,关于整数类型的实现,我有点小疑惑。
简单看一下小整数的实现(完整代码在最下面),在for循环里,首先看到第一句size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1);
这里面size会根据ival的正负来分别取-1/0/1。然后是进行引用计数的更新(由于小整数是一定会天地同寿的这里就不分析了)。
接下来可以看到,代码中的这两行Py_SIZE(v) = size;
v->ob_digit[0] = (digit)abs(ival);
第二行很显然是把ival对应值取绝对值以后送到存储空间中,但是第一行我就觉得不是特别懂,因为size在这里很显然是ival的符号,但是却赋给了v的size。
进一步地,我看到Py_SIZE的实现typedef struct {
PyObject ob_base;
Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;
/* Cast argument to PyVarObject* type. */
#define _PyVarObject_CAST(op) ((PyVarObject*)(op))
#define Py_SIZE(ob) (_PyVarObject_CAST(ob)->ob_size)
可以看到,这个Py_SIZE(ob)是将ob->ob_size赋值的一个宏定义。而ob_size对应的是类的元素个数,如果传入一个负值或者0,这个地方岂不是很离谱?还是说Python底层实现的时候对于整数类型的这个地方有什么特殊的处理?
以下是详细代码# longobject.c
int
_PyLong_Init(void)
{
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
int ival, size;
PyLongObject *v = small_ints;
for (ival = -NSMALLNEGINTS; ival < NSMALLPOSINTS; ival++, v++) {
size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1);
if (Py_TYPE(v) == &PyLong_Type) {
/* The element is already initialized, most likely
* the Python interpreter was initialized before.
*/
Py_ssize_t refcnt;
PyObject* op = (PyObject*)v;
refcnt = Py_REFCNT(op) < 0 ? 0 : Py_REFCNT(op);
_Py_NewReference(op);
/* _Py_NewReference sets the ref count to 1 but
* the ref count might be larger. Set the refcnt
* to the original refcnt + 1 */
Py_REFCNT(op) = refcnt + 1;
assert(Py_SIZE(op) == size);
assert(v->ob_digit[0] == (digit)abs(ival));
}
else {
(void)PyObject_INIT(v, &PyLong_Type);
}
Py_SIZE(v) = size;
v->ob_digit[0] = (digit)abs(ival);
}
#endif
_PyLong_Zero = PyLong_FromLong(0);
if (_PyLong_Zero == NULL)
return 0;
_PyLong_One = PyLong_FromLong(1);
if (_PyLong_One == NULL)
return 0;
/* initialize int_info */
if (Int_InfoType.tp_name == NULL) {
if (PyStructSequence_InitType2(&Int_InfoType, &int_info_desc) < 0) {
return 0;
}
}
return 1;
}
|