|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
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;
- }
复制代码
|
|